diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 2f880a9e32..6934354a70 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,33 +1,49 @@
+---
+name: Bug report
+about: Create a report to help us fix issues.
+title: ''
+labels: 'Type: Bug'
+assignees: ''
+
+---
+
-**Application Version**
-
+**Application version**
+(The version of the application this issue occurs with.)
**Platform**
-
+(Information about the operating system the issue occurs on. Include at least the operating system and maybe GPU.)
**Printer**
-
+(Which printer was selected in Cura?)
-**Steps to Reproduce**
-
+**Reproduction steps**
+1. (Something you did.)
+2. (Something you did next.)
-**Actual Results**
-
+**Screenshot(s)**
+(Image showing the problem, perhaps before/after images.)
+
+**Actual results**
+(What happens after the above steps have been followed.)
**Expected results**
-
+(What should happen after the above steps have been followed.)
-**Additional Information**
-
+**Project file**
+(For slicing bugs, provide a project which clearly shows the bug, by going to File->Save. For big files you may need to use WeTransfer or similar file sharing sites.)
+
+**Log file**
+(See https://github.com/Ultimaker/Cura#logging-issues to find the log file to upload, or copy a relevant snippet from it.)
+
+**Additional information**
+(Extra information relevant to the issue.)
diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
new file mode 100644
index 0000000000..6934354a70
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -0,0 +1,49 @@
+---
+name: Bug report
+about: Create a report to help us fix issues.
+title: ''
+labels: 'Type: Bug'
+assignees: ''
+
+---
+
+
+
+**Application version**
+(The version of the application this issue occurs with.)
+
+**Platform**
+(Information about the operating system the issue occurs on. Include at least the operating system and maybe GPU.)
+
+**Printer**
+(Which printer was selected in Cura?)
+
+**Reproduction steps**
+1. (Something you did.)
+2. (Something you did next.)
+
+**Screenshot(s)**
+(Image showing the problem, perhaps before/after images.)
+
+**Actual results**
+(What happens after the above steps have been followed.)
+
+**Expected results**
+(What should happen after the above steps have been followed.)
+
+**Project file**
+(For slicing bugs, provide a project which clearly shows the bug, by going to File->Save. For big files you may need to use WeTransfer or similar file sharing sites.)
+
+**Log file**
+(See https://github.com/Ultimaker/Cura#logging-issues to find the log file to upload, or copy a relevant snippet from it.)
+
+**Additional information**
+(Extra information relevant to the issue.)
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000..a10d664a04
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,23 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: 'Type: New Feature'
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+(A clear and concise description of what the problem is. Ex. I'm always frustrated when [...])
+
+**Describe the solution you'd like**
+(A clear and concise description of what you want to happen. If possible, describe why you think this is a good solution.)
+
+**Describe alternatives you've considered**
+(A clear and concise description of any alternative solutions or features you've considered. Again, if possible, think about why these alternatives are not working out.)
+
+**Affected users and/or printers**
+(Who do you think will benefit from this? Is everyone going to benefit from these changes? Or specific kinds of users?)
+
+**Additional context**
+(Add any other context or screenshots about the feature request here.)
diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml
new file mode 100644
index 0000000000..3a0b57d714
--- /dev/null
+++ b/.github/workflows/cicd.yml
@@ -0,0 +1,13 @@
+---
+name: CI/CD
+on: [push, pull_request]
+jobs:
+ build:
+ name: Build and test
+ runs-on: ubuntu-latest
+ container: ultimaker/cura-build-environment
+ steps:
+ - name: Checkout master
+ uses: actions/checkout@v1.2.0
+ - name: Build and test
+ run: docker/build.sh
diff --git a/.gitignore b/.gitignore
index 60b59e6829..eed686fda7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,7 +35,7 @@ cura.desktop
.pydevproject
.settings
-#Externally located plug-ins.
+#Externally located plug-ins commonly installed by our devs.
plugins/cura-big-flame-graph
plugins/cura-god-mode-plugin
plugins/cura-siemensnx-plugin
@@ -52,6 +52,7 @@ plugins/FlatProfileExporter
plugins/GodMode
plugins/OctoPrintPlugin
plugins/ProfileFlattener
+plugins/SettingsGuide
plugins/X3GWriter
#Build stuff
@@ -71,3 +72,7 @@ run.sh
.scannerwork/
CuraEngine
+/.coverage
+
+#Prevents import failures when plugin running tests
+plugins/__init__.py
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000..6c5bc61cbe
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,16 @@
+image: registry.gitlab.com/ultimaker/cura/cura-build-environment:centos7
+
+stages:
+ - build
+
+build and test linux:
+ stage: build
+ tags:
+ - cura
+ - docker
+ - linux
+ script:
+ - docker/build.sh
+ artifacts:
+ paths:
+ - build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index be6c9d938e..4954ac46dc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,10 @@
-project(cura NONE)
-cmake_minimum_required(VERSION 2.8.12)
-
-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/
- ${CMAKE_MODULE_PATH})
+project(cura)
+cmake_minimum_required(VERSION 3.6)
include(GNUInstallDirs)
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
+
set(URANIUM_DIR "${CMAKE_SOURCE_DIR}/../Uranium" CACHE DIRECTORY "The location of the Uranium repository")
set(URANIUM_SCRIPTS_DIR "${URANIUM_DIR}/scripts" CACHE DIRECTORY "The location of the scripts directory of the Uranium repository")
@@ -21,15 +20,36 @@ set(CURA_APP_NAME "cura" CACHE STRING "Short name of Cura, used for configuratio
set(CURA_APP_DISPLAY_NAME "Ultimaker Cura" CACHE STRING "Display name of Cura")
set(CURA_VERSION "master" CACHE STRING "Version name of Cura")
set(CURA_BUILDTYPE "" CACHE STRING "Build type of Cura, eg. 'PPA'")
-set(CURA_SDK_VERSION "" CACHE STRING "SDK version of Cura")
set(CURA_CLOUD_API_ROOT "" CACHE STRING "Alternative Cura cloud API root")
set(CURA_CLOUD_API_VERSION "" CACHE STRING "Alternative Cura cloud API version")
+set(CURA_CLOUD_ACCOUNT_API_ROOT "" CACHE STRING "Alternative Cura cloud account API version")
configure_file(${CMAKE_SOURCE_DIR}/cura.desktop.in ${CMAKE_BINARY_DIR}/cura.desktop @ONLY)
+
configure_file(cura/CuraVersion.py.in CuraVersion.py @ONLY)
+
+# FIXME: Remove the code for CMake <3.12 once we have switched over completely.
+# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
+# module is copied from the CMake repository here so in CMake <3.12 we can still use it.
+if(${CMAKE_VERSION} VERSION_LESS 3.12)
+ # Use FindPythonInterp and FindPythonLibs for CMake <3.12
+ find_package(PythonInterp 3 REQUIRED)
+
+ set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
+
+ set(Python3_VERSION ${PYTHON_VERSION_STRING})
+ set(Python3_VERSION_MAJOR ${PYTHON_VERSION_MAJOR})
+ set(Python3_VERSION_MINOR ${PYTHON_VERSION_MINOR})
+ set(Python3_VERSION_PATCH ${PYTHON_VERSION_PATCH})
+else()
+ # Use FindPython3 for CMake >=3.12
+ find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+endif()
+
+
if(NOT ${URANIUM_DIR} STREQUAL "")
- set(CMAKE_MODULE_PATH "${URANIUM_DIR}/cmake")
+ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${URANIUM_DIR}/cmake")
endif()
if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
list(APPEND CMAKE_MODULE_PATH ${URANIUM_DIR}/cmake)
@@ -40,12 +60,12 @@ if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
CREATE_TRANSLATION_TARGETS()
endif()
-find_package(PythonInterp 3.5.0 REQUIRED)
install(DIRECTORY resources
DESTINATION ${CMAKE_INSTALL_DATADIR}/cura)
-install(DIRECTORY plugins
- DESTINATION lib${LIB_SUFFIX}/cura)
+
+include(CuraPluginInstall)
+
if(NOT APPLE AND NOT WIN32)
install(FILES cura_app.py
DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -53,16 +73,16 @@ if(NOT APPLE AND NOT WIN32)
RENAME cura)
if(EXISTS /etc/debian_version)
install(DIRECTORY cura
- DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}/dist-packages
+ DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}/dist-packages
FILES_MATCHING PATTERN *.py)
install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py
- DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}/dist-packages/cura)
+ DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}/dist-packages/cura)
else()
install(DIRECTORY cura
- DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages
+ DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages
FILES_MATCHING PATTERN *.py)
install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py
- DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/cura)
+ DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages/cura)
endif()
install(FILES ${CMAKE_BINARY_DIR}/cura.desktop
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
@@ -78,8 +98,8 @@ else()
DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(DIRECTORY cura
- DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages
+ DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages
FILES_MATCHING PATTERN *.py)
install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py
- DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/cura)
+ DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages/cura)
endif()
diff --git a/cmake/CuraPluginInstall.cmake b/cmake/CuraPluginInstall.cmake
new file mode 100644
index 0000000000..d35e74acb8
--- /dev/null
+++ b/cmake/CuraPluginInstall.cmake
@@ -0,0 +1,99 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# CuraPluginInstall.cmake is released under the terms of the LGPLv3 or higher.
+
+#
+# This module detects all plugins that need to be installed and adds them using the CMake install() command.
+# It detects all plugin folder in the path "plugins/*" where there's a "plugin.json" in it.
+#
+# Plugins can be configured to NOT BE INSTALLED via the variable "CURA_NO_INSTALL_PLUGINS" as a list of string in the
+# form of "a;b;c" or "a,b,c". By default all plugins will be installed.
+#
+
+# FIXME: Remove the code for CMake <3.12 once we have switched over completely.
+# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
+# module is copied from the CMake repository here so in CMake <3.12 we can still use it.
+if(${CMAKE_VERSION} VERSION_LESS 3.12)
+ # Use FindPythonInterp and FindPythonLibs for CMake <3.12
+ find_package(PythonInterp 3 REQUIRED)
+
+ set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
+else()
+ # Use FindPython3 for CMake >=3.12
+ find_package(Python3 REQUIRED COMPONENTS Interpreter)
+endif()
+
+# Options or configuration variables
+set(CURA_NO_INSTALL_PLUGINS "" CACHE STRING "A list of plugins that should not be installed, separated with ';' or ','.")
+
+file(GLOB_RECURSE _plugin_json_list ${CMAKE_SOURCE_DIR}/plugins/*/plugin.json)
+list(LENGTH _plugin_json_list _plugin_json_list_len)
+
+# Sort the lists alphabetically so we can handle cases like this:
+# - plugins/my_plugin/plugin.json
+# - plugins/my_plugin/my_module/plugin.json
+# In this case, only "plugins/my_plugin" should be added via install().
+set(_no_install_plugin_list ${CURA_NO_INSTALL_PLUGINS})
+# Sanitize the string so the comparison will be case-insensitive.
+string(STRIP "${_no_install_plugin_list}" _no_install_plugin_list)
+string(TOLOWER "${_no_install_plugin_list}" _no_install_plugin_list)
+
+# WORKAROUND counterpart of what's in cura-build.
+string(REPLACE "," ";" _no_install_plugin_list "${_no_install_plugin_list}")
+
+list(LENGTH _no_install_plugin_list _no_install_plugin_list_len)
+
+if(_no_install_plugin_list_len GREATER 0)
+ list(SORT _no_install_plugin_list)
+endif()
+if(_plugin_json_list_len GREATER 0)
+ list(SORT _plugin_json_list)
+endif()
+
+# Check all plugin directories and add them via install() if needed.
+set(_install_plugin_list "")
+foreach(_plugin_json_path ${_plugin_json_list})
+ get_filename_component(_plugin_dir ${_plugin_json_path} DIRECTORY)
+ file(RELATIVE_PATH _rel_plugin_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_plugin_dir})
+ get_filename_component(_plugin_dir_name ${_plugin_dir} NAME)
+
+ # Make plugin name comparison case-insensitive
+ string(TOLOWER "${_plugin_dir_name}" _plugin_dir_name_lowercase)
+
+ # Check if this plugin needs to be skipped for installation
+ set(_add_plugin ON) # Indicates if this plugin should be added to the build or not.
+ set(_is_no_install_plugin OFF) # If this plugin will not be added, this indicates if it's because the plugin is
+ # specified in the NO_INSTALL_PLUGINS list.
+ if(_no_install_plugin_list)
+ if("${_plugin_dir_name_lowercase}" IN_LIST _no_install_plugin_list)
+ set(_add_plugin OFF)
+ set(_is_no_install_plugin ON)
+ endif()
+ endif()
+
+ # Make sure this is not a subdirectory in a plugin that's already in the install list
+ if(_add_plugin)
+ foreach(_known_install_plugin_dir ${_install_plugin_list})
+ if(_plugin_dir MATCHES "${_known_install_plugin_dir}.+")
+ set(_add_plugin OFF)
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ if(_add_plugin)
+ message(STATUS "[+] PLUGIN TO INSTALL: ${_rel_plugin_dir}")
+ get_filename_component(_rel_plugin_parent_dir ${_rel_plugin_dir} DIRECTORY)
+ install(DIRECTORY ${_rel_plugin_dir}
+ DESTINATION lib${LIB_SUFFIX}/cura/${_rel_plugin_parent_dir}
+ PATTERN "__pycache__" EXCLUDE
+ PATTERN "*.qmlc" EXCLUDE
+ )
+ list(APPEND _install_plugin_list ${_plugin_dir})
+ elseif(_is_no_install_plugin)
+ message(STATUS "[-] PLUGIN TO REMOVE : ${_rel_plugin_dir}")
+ execute_process(COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mod_bundled_packages_json.py
+ -d ${CMAKE_CURRENT_SOURCE_DIR}/resources/bundled_packages
+ ${_plugin_dir_name}
+ RESULT_VARIABLE _mod_json_result)
+ endif()
+endforeach()
diff --git a/cmake/CuraTests.cmake b/cmake/CuraTests.cmake
index b6d04de036..b1d3e0ddc4 100644
--- a/cmake/CuraTests.cmake
+++ b/cmake/CuraTests.cmake
@@ -1,10 +1,21 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-enable_testing()
+include(CTest)
include(CMakeParseArguments)
-find_package(PythonInterp 3.5.0 REQUIRED)
+# FIXME: Remove the code for CMake <3.12 once we have switched over completely.
+# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. The FindPython3
+# module is copied from the CMake repository here so in CMake <3.12 we can still use it.
+if(${CMAKE_VERSION} VERSION_LESS 3.12)
+ # Use FindPythonInterp and FindPythonLibs for CMake <3.12
+ find_package(PythonInterp 3 REQUIRED)
+
+ set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
+else()
+ # Use FindPython3 for CMake >=3.12
+ find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+endif()
add_custom_target(test-verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
@@ -36,7 +47,7 @@ function(cura_add_test)
if (NOT ${test_exists})
add_test(
NAME ${_NAME}
- COMMAND ${PYTHON_EXECUTABLE} -m pytest --verbose --full-trace --capture=no --no-print-log --junitxml=${CMAKE_BINARY_DIR}/junit-${_NAME}.xml ${_DIRECTORY}
+ COMMAND ${Python3_EXECUTABLE} -m pytest --junitxml=${CMAKE_BINARY_DIR}/junit-${_NAME}.xml ${_DIRECTORY}
)
set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT LANG=C)
set_tests_properties(${_NAME} PROPERTIES ENVIRONMENT "PYTHONPATH=${_PYTHONPATH}")
@@ -59,13 +70,13 @@ endforeach()
#Add code style test.
add_test(
NAME "code-style"
- COMMAND ${PYTHON_EXECUTABLE} run_mypy.py
+ COMMAND ${Python3_EXECUTABLE} run_mypy.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
#Add test for whether the shortcut alt-keys are unique in every translation.
add_test(
NAME "shortcut-keys"
- COMMAND ${PYTHON_EXECUTABLE} scripts/check_shortcut_keys.py
+ COMMAND ${Python3_EXECUTABLE} scripts/check_shortcut_keys.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-)
\ No newline at end of file
+)
diff --git a/cmake/mod_bundled_packages_json.py b/cmake/mod_bundled_packages_json.py
new file mode 100755
index 0000000000..6423591f57
--- /dev/null
+++ b/cmake/mod_bundled_packages_json.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# This script removes the given package entries in the bundled_packages JSON files. This is used by the PluginInstall
+# CMake module.
+#
+
+import argparse
+import collections
+import json
+import os
+import sys
+
+
+## Finds all JSON files in the given directory recursively and returns a list of those files in absolute paths.
+#
+# \param work_dir The directory to look for JSON files recursively.
+# \return A list of JSON files in absolute paths that are found in the given directory.
+def find_json_files(work_dir: str) -> list:
+ json_file_list = []
+ for root, dir_names, file_names in os.walk(work_dir):
+ for file_name in file_names:
+ abs_path = os.path.abspath(os.path.join(root, file_name))
+ json_file_list.append(abs_path)
+ return json_file_list
+
+
+## Removes the given entries from the given JSON file. The file will modified in-place.
+#
+# \param file_path The JSON file to modify.
+# \param entries A list of strings as entries to remove.
+# \return None
+def remove_entries_from_json_file(file_path: str, entries: list) -> None:
+ try:
+ with open(file_path, "r", encoding = "utf-8") as f:
+ package_dict = json.load(f, object_hook = collections.OrderedDict)
+ except Exception as e:
+ msg = "Failed to load '{file_path}' as a JSON file. This file will be ignored Exception: {e}"\
+ .format(file_path = file_path, e = e)
+ sys.stderr.write(msg + os.linesep)
+ return
+
+ for entry in entries:
+ if entry in package_dict:
+ del package_dict[entry]
+ print("[INFO] Remove entry [{entry}] from [{file_path}]".format(file_path = file_path, entry = entry))
+
+ try:
+ with open(file_path, "w", encoding = "utf-8", newline = "\n") as f:
+ json.dump(package_dict, f, indent = 4)
+ except Exception as e:
+ msg = "Failed to write '{file_path}' as a JSON file. Exception: {e}".format(file_path = file_path, e = e)
+ raise IOError(msg)
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser("mod_bundled_packages_json")
+ parser.add_argument("-d", "--dir", dest = "work_dir",
+ help = "The directory to look for bundled packages JSON files, recursively.")
+ parser.add_argument("entries", metavar = "ENTRIES", type = str, nargs = "+")
+
+ args = parser.parse_args()
+
+ json_file_list = find_json_files(args.work_dir)
+ for json_file_path in json_file_list:
+ remove_entries_from_json_file(json_file_path, args.entries)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/cura.desktop.in b/cura.desktop.in
index b0195015a5..1e17e30f4e 100644
--- a/cura.desktop.in
+++ b/cura.desktop.in
@@ -13,6 +13,7 @@ TryExec=@CMAKE_INSTALL_FULL_BINDIR@/cura
Icon=cura-icon
Terminal=false
Type=Application
-MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;image/bmp;image/gif;image/jpeg;image/png;model/x3d+xml;text/x-gcode;
+MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;image/bmp;image/gif;image/jpeg;image/png;text/x-gcode;application/x-amf;application/x-ply;application/x-ctm;model/vnd.collada+xml;model/gltf-binary;model/gltf+json;model/vnd.collada+xml+zip;
Categories=Graphics;
Keywords=3D;Printing;Slicer;
+StartupWMClass=cura.real
diff --git a/cura/API/Account.py b/cura/API/Account.py
index 30401454b3..0e3af0e6c1 100644
--- a/cura/API/Account.py
+++ b/cura/API/Account.py
@@ -29,6 +29,7 @@ i18n_catalog = i18nCatalog("cura")
class Account(QObject):
# Signal emitted when user logged in or out.
loginStateChanged = pyqtSignal(bool)
+ accessTokenChanged = pyqtSignal()
def __init__(self, application: "CuraApplication", parent = None) -> None:
super().__init__(parent)
@@ -59,8 +60,12 @@ class Account(QObject):
self._authorization_service.initialize(self._application.getPreferences())
self._authorization_service.onAuthStateChanged.connect(self._onLoginStateChanged)
self._authorization_service.onAuthenticationError.connect(self._onLoginStateChanged)
+ self._authorization_service.accessTokenChanged.connect(self._onAccessTokenChanged)
self._authorization_service.loadAuthDataFromPreferences()
+ def _onAccessTokenChanged(self):
+ self.accessTokenChanged.emit()
+
## Returns a boolean indicating whether the given authentication is applied against staging or not.
@property
def is_staging(self) -> bool:
@@ -105,7 +110,7 @@ class Account(QObject):
return None
return user_profile.profile_image_url
- @pyqtProperty(str, notify=loginStateChanged)
+ @pyqtProperty(str, notify=accessTokenChanged)
def accessToken(self) -> Optional[str]:
return self._authorization_service.getAccessToken()
diff --git a/cura/ApplicationMetadata.py b/cura/ApplicationMetadata.py
index faa3364e08..427cc77e65 100644
--- a/cura/ApplicationMetadata.py
+++ b/cura/ApplicationMetadata.py
@@ -9,7 +9,11 @@ DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura"
DEFAULT_CURA_VERSION = "master"
DEFAULT_CURA_BUILD_TYPE = ""
DEFAULT_CURA_DEBUG_MODE = False
-DEFAULT_CURA_SDK_VERSION = "6.0.0"
+
+# Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for
+# example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the
+# CuraVersion.py.in template.
+CuraSDKVersion = "7.0.0"
try:
from cura.CuraVersion import CuraAppName # type: ignore
@@ -32,6 +36,9 @@ try:
except ImportError:
CuraVersion = DEFAULT_CURA_VERSION # [CodeStyle: Reflecting imported value]
+# CURA-6569
+# This string indicates what type of version it is. For example, "enterprise". By default it's empty which indicates
+# a default/normal Cura build.
try:
from cura.CuraVersion import CuraBuildType # type: ignore
except ImportError:
@@ -42,9 +49,7 @@ try:
except ImportError:
CuraDebugMode = DEFAULT_CURA_DEBUG_MODE
-try:
- from cura.CuraVersion import CuraSDKVersion # type: ignore
- if CuraSDKVersion == "":
- CuraSDKVersion = DEFAULT_CURA_SDK_VERSION
-except ImportError:
- CuraSDKVersion = DEFAULT_CURA_SDK_VERSION
+# CURA-6569
+# Various convenience flags indicating what kind of Cura build it is.
+__ENTERPRISE_VERSION_TYPE = "enterprise"
+IsEnterpriseVersion = CuraBuildType.lower() == __ENTERPRISE_VERSION_TYPE
diff --git a/cura/Arranging/Arrange.py b/cura/Arranging/Arrange.py
index 32796005c8..caa7aae910 100644
--- a/cura/Arranging/Arrange.py
+++ b/cura/Arranging/Arrange.py
@@ -217,11 +217,6 @@ class Arrange:
prio_slice = self._priority[min_y:max_y, min_x:max_x]
prio_slice[new_occupied] = 999
- # If you want to see how the rasterized arranger build plate looks like, uncomment this code
- # numpy.set_printoptions(linewidth=500, edgeitems=200)
- # print(self._occupied.shape)
- # print(self._occupied)
-
@property
def isEmpty(self):
return self._is_empty
diff --git a/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py b/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py
index 8bbc2bf132..89f613e180 100644
--- a/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py
+++ b/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Application import Application
@@ -48,7 +48,6 @@ class ArrangeArray:
return self._count
def get(self, index):
- print(self._arrange)
return self._arrange[index]
def getFirstEmpty(self):
diff --git a/cura/Arranging/ShapeArray.py b/cura/Arranging/ShapeArray.py
index 64b78d6f17..403db5e706 100644
--- a/cura/Arranging/ShapeArray.py
+++ b/cura/Arranging/ShapeArray.py
@@ -1,12 +1,19 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
import numpy
import copy
+from typing import Optional, Tuple, TYPE_CHECKING
from UM.Math.Polygon import Polygon
+if TYPE_CHECKING:
+ from UM.Scene.SceneNode import SceneNode
+
## Polygon representation as an array for use with Arrange
class ShapeArray:
- def __init__(self, arr, offset_x, offset_y, scale = 1):
+ def __init__(self, arr: numpy.array, offset_x: float, offset_y: float, scale: float = 1) -> None:
self.arr = arr
self.offset_x = offset_x
self.offset_y = offset_y
@@ -16,7 +23,7 @@ class ShapeArray:
# \param vertices
# \param scale scale the coordinates
@classmethod
- def fromPolygon(cls, vertices, scale = 1):
+ def fromPolygon(cls, vertices: numpy.array, scale: float = 1) -> "ShapeArray":
# scale
vertices = vertices * scale
# flip y, x -> x, y
@@ -42,7 +49,7 @@ class ShapeArray:
# \param min_offset offset for the offset ShapeArray
# \param scale scale the coordinates
@classmethod
- def fromNode(cls, node, min_offset, scale = 0.5, include_children = False):
+ def fromNode(cls, node: "SceneNode", min_offset: float, scale: float = 0.5, include_children: bool = False) -> Tuple[Optional["ShapeArray"], Optional["ShapeArray"]]:
transform = node._transformation
transform_x = transform._data[0][3]
transform_y = transform._data[2][3]
@@ -88,14 +95,16 @@ class ShapeArray:
# \param shape numpy format shape, [x-size, y-size]
# \param vertices
@classmethod
- def arrayFromPolygon(cls, shape, vertices):
+ def arrayFromPolygon(cls, shape: Tuple[int, int], vertices: numpy.array) -> numpy.array:
base_array = numpy.zeros(shape, dtype = numpy.int32) # Initialize your array of zeros
fill = numpy.ones(base_array.shape) * True # Initialize boolean array defining shape fill
# Create check array for each edge segment, combine into fill array
for k in range(vertices.shape[0]):
- fill = numpy.all([fill, cls._check(vertices[k - 1], vertices[k], base_array)], axis=0)
+ check_array = cls._check(vertices[k - 1], vertices[k], base_array)
+ if check_array is not None:
+ fill = numpy.all([fill, check_array], axis=0)
# Set all values inside polygon to one
base_array[fill] = 1
@@ -111,9 +120,9 @@ class ShapeArray:
# \param p2 2-tuple with x, y for point 2
# \param base_array boolean array to project the line on
@classmethod
- def _check(cls, p1, p2, base_array):
+ def _check(cls, p1: numpy.array, p2: numpy.array, base_array: numpy.array) -> Optional[numpy.array]:
if p1[0] == p2[0] and p1[1] == p2[1]:
- return
+ return None
idxs = numpy.indices(base_array.shape) # Create 3D array of indices
p1 = p1.astype(float)
@@ -131,5 +140,4 @@ class ShapeArray:
max_col_idx = (idxs[0] - p1[0]) / (p2[0] - p1[0]) * (p2[1] - p1[1]) + p1[1]
sign = numpy.sign(p2[0] - p1[0])
- return idxs[1] * sign <= max_col_idx * sign
-
+ return idxs[1] * sign <= max_col_idx * sign
\ No newline at end of file
diff --git a/cura/AutoSave.py b/cura/AutoSave.py
index 1639868d6a..3b42fdafdf 100644
--- a/cura/AutoSave.py
+++ b/cura/AutoSave.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import QTimer
@@ -16,9 +16,10 @@ class AutoSave:
self._application.getPreferences().addPreference("cura/autosave_delay", 1000 * 10)
self._change_timer = QTimer()
- self._change_timer.setInterval(self._application.getPreferences().getValue("cura/autosave_delay"))
+ self._change_timer.setInterval(int(self._application.getPreferences().getValue("cura/autosave_delay")))
self._change_timer.setSingleShot(True)
+ self._enabled = True
self._saving = False
def initialize(self):
@@ -32,6 +33,13 @@ class AutoSave:
if not self._saving:
self._change_timer.start()
+ def setEnabled(self, enabled: bool) -> None:
+ self._enabled = enabled
+ if self._enabled:
+ self._change_timer.start()
+ else:
+ self._change_timer.stop()
+
def _onGlobalStackChanged(self):
if self._global_stack:
self._global_stack.propertyChanged.disconnect(self._triggerTimer)
diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py
index 714d6527fe..9ccdcaf64d 100644
--- a/cura/Backups/Backup.py
+++ b/cura/Backups/Backup.py
@@ -116,12 +116,13 @@ class Backup:
current_version = self._application.getVersion()
version_to_restore = self.meta_data.get("cura_release", "master")
- if current_version != version_to_restore:
- # Cannot restore version older or newer than current because settings might have changed.
- # Restoring this will cause a lot of issues so we don't allow this for now.
+
+ if current_version < version_to_restore:
+ # Cannot restore version newer than current because settings might have changed.
+ Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version))
self._showMessage(
self.catalog.i18nc("@info:backup_failed",
- "Tried to restore a Cura backup that does not match your current version."))
+ "Tried to restore a Cura backup that is higher than the current version."))
return False
version_data_dir = Resources.getDataStoragePath()
@@ -147,5 +148,9 @@ class Backup:
Logger.log("d", "Removing current data in location: %s", target_path)
Resources.factoryReset()
Logger.log("d", "Extracting backup to location: %s", target_path)
- archive.extractall(target_path)
+ try:
+ archive.extractall(target_path)
+ except PermissionError:
+ Logger.logException("e", "Unable to extract the backup due to permission errors")
+ return False
return True
diff --git a/cura/Backups/BackupsManager.py b/cura/Backups/BackupsManager.py
index a0d3881209..ba6fcab8d7 100644
--- a/cura/Backups/BackupsManager.py
+++ b/cura/Backups/BackupsManager.py
@@ -51,8 +51,18 @@ class BackupsManager:
## Here we try to disable the auto-save plug-in as it might interfere with
# restoring a back-up.
def _disableAutoSave(self) -> None:
- self._application.setSaveDataEnabled(False)
+ auto_save = self._application.getAutoSave()
+ # The auto save is only not created if the application has not yet started.
+ if auto_save:
+ auto_save.setEnabled(False)
+ else:
+ Logger.log("e", "Unable to disable the autosave as application init has not been completed")
## Re-enable auto-save after we're done.
def _enableAutoSave(self) -> None:
- self._application.setSaveDataEnabled(True)
+ auto_save = self._application.getAutoSave()
+ # The auto save is only not created if the application has not yet started.
+ if auto_save:
+ auto_save.setEnabled(True)
+ else:
+ Logger.log("e", "Unable to enable the autosave as application init has not been completed")
diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py
index f8f691a850..aba94e8c60 100755
--- a/cura/BuildVolume.py
+++ b/cura/BuildVolume.py
@@ -1,6 +1,6 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from UM.Scene.Camera import Camera
+from UM.Mesh.MeshData import MeshData
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Settings.ExtruderManager import ExtruderManager
from UM.Application import Application #To modify the maximum zoom level.
@@ -20,13 +20,19 @@ from UM.Signal import Signal
from PyQt5.QtCore import QTimer
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
+from cura.Settings.GlobalStack import GlobalStack
+
catalog = i18nCatalog("cura")
import numpy
import math
-import copy
-from typing import List, Optional
+from typing import List, Optional, TYPE_CHECKING, Any, Set, cast, Iterable, Dict
+
+if TYPE_CHECKING:
+ from cura.CuraApplication import CuraApplication
+ from cura.Settings.ExtruderStack import ExtruderStack
+ from UM.Settings.ContainerStack import ContainerStack
# Radius of disallowed area in mm around prime. I.e. how much distance to keep from prime position.
PRIME_CLEARANCE = 6.5
@@ -36,45 +42,47 @@ PRIME_CLEARANCE = 6.5
class BuildVolume(SceneNode):
raftThicknessChanged = Signal()
- def __init__(self, application, parent = None):
+ def __init__(self, application: "CuraApplication", parent: Optional[SceneNode] = None) -> None:
super().__init__(parent)
self._application = application
self._machine_manager = self._application.getMachineManager()
- self._volume_outline_color = None
- self._x_axis_color = None
- self._y_axis_color = None
- self._z_axis_color = None
- self._disallowed_area_color = None
- self._error_area_color = None
+ self._volume_outline_color = None # type: Optional[Color]
+ self._x_axis_color = None # type: Optional[Color]
+ self._y_axis_color = None # type: Optional[Color]
+ self._z_axis_color = None # type: Optional[Color]
+ self._disallowed_area_color = None # type: Optional[Color]
+ self._error_area_color = None # type: Optional[Color]
- self._width = 0 #type: float
- self._height = 0 #type: float
- self._depth = 0 #type: float
- self._shape = "" #type: str
+ self._width = 0 # type: float
+ self._height = 0 # type: float
+ self._depth = 0 # type: float
+ self._shape = "" # type: str
self._shader = None
- self._origin_mesh = None
+ self._origin_mesh = None # type: Optional[MeshData]
self._origin_line_length = 20
- self._origin_line_width = 0.5
+ self._origin_line_width = 1.5
+ self._enabled = False
- self._grid_mesh = None
+ self._grid_mesh = None # type: Optional[MeshData]
self._grid_shader = None
- self._disallowed_areas = []
- self._disallowed_areas_no_brim = []
- self._disallowed_area_mesh = None
+ self._disallowed_areas = [] # type: List[Polygon]
+ self._disallowed_areas_no_brim = [] # type: List[Polygon]
+ self._disallowed_area_mesh = None # type: Optional[MeshData]
+ self._disallowed_area_size = 0.
- self._error_areas = []
- self._error_mesh = None
+ self._error_areas = [] # type: List[Polygon]
+ self._error_mesh = None # type: Optional[MeshData]
self.setCalculateBoundingBox(False)
- self._volume_aabb = None
+ self._volume_aabb = None # type: Optional[AxisAlignedBox]
self._raft_thickness = 0.0
self._extra_z_clearance = 0.0
- self._adhesion_type = None
+ self._adhesion_type = None # type: Any
self._platform = Platform(self)
self._build_volume_message = Message(catalog.i18nc("@info:status",
@@ -82,7 +90,7 @@ class BuildVolume(SceneNode):
" \"Print Sequence\" setting to prevent the gantry from colliding"
" with printed models."), title = catalog.i18nc("@info:title", "Build Volume"))
- self._global_container_stack = None
+ self._global_container_stack = None # type: Optional[GlobalStack]
self._stack_change_timer = QTimer()
self._stack_change_timer.setInterval(100)
@@ -100,7 +108,7 @@ class BuildVolume(SceneNode):
self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged)
#Objects loaded at the moment. We are connected to the property changed events of these objects.
- self._scene_objects = set()
+ self._scene_objects = set() # type: Set[SceneNode]
self._scene_change_timer = QTimer()
self._scene_change_timer.setInterval(100)
@@ -117,15 +125,11 @@ class BuildVolume(SceneNode):
# Therefore this works.
self._machine_manager.activeQualityChanged.connect(self._onStackChanged)
- # This should also ways work, and it is semantically more correct,
- # but it does not update the disallowed areas after material change
- self._machine_manager.activeStackChanged.connect(self._onStackChanged)
-
# Enable and disable extruder
self._machine_manager.extruderChanged.connect(self.updateNodeBoundaryCheck)
- # list of settings which were updated
- self._changed_settings_since_last_rebuild = []
+ # List of settings which were updated
+ self._changed_settings_since_last_rebuild = [] # type: List[str]
def _onSceneChanged(self, source):
if self._global_container_stack:
@@ -165,16 +169,13 @@ class BuildVolume(SceneNode):
active_extruder_changed.connect(self._updateDisallowedAreasAndRebuild)
def setWidth(self, width: float) -> None:
- if width is not None:
- self._width = width
+ self._width = width
def setHeight(self, height: float) -> None:
- if height is not None:
- self._height = height
+ self._height = height
def setDepth(self, depth: float) -> None:
- if depth is not None:
- self._depth = depth
+ self._depth = depth
def setShape(self, shape: str) -> None:
if shape:
@@ -196,7 +197,7 @@ class BuildVolume(SceneNode):
self._disallowed_areas = areas
def render(self, renderer):
- if not self.getMeshData():
+ if not self.getMeshData() or not self.isVisible():
return True
if not self._shader:
@@ -222,13 +223,18 @@ class BuildVolume(SceneNode):
## For every sliceable node, update node._outside_buildarea
#
def updateNodeBoundaryCheck(self):
+ if not self._global_container_stack:
+ return
+
root = self._application.getController().getScene().getRoot()
- nodes = list(BreadthFirstIterator(root))
- group_nodes = []
+ nodes = cast(List[SceneNode], list(cast(Iterable, BreadthFirstIterator(root))))
+ group_nodes = [] # type: List[SceneNode]
build_volume_bounding_box = self.getBoundingBox()
if build_volume_bounding_box:
# It's over 9000!
+ # We set this to a very low number, as we do allow models to intersect the build plate.
+ # This means the model gets cut off at the build plate.
build_volume_bounding_box = build_volume_bounding_box.set(bottom=-9001)
else:
# No bounding box. This is triggered when running Cura from command line with a model for the first time
@@ -241,20 +247,28 @@ class BuildVolume(SceneNode):
group_nodes.append(node) # Keep list of affected group_nodes
if node.callDecoration("isSliceable") or node.callDecoration("isGroup"):
+ if not isinstance(node, CuraSceneNode):
+ continue
+
if node.collidesWithBbox(build_volume_bounding_box):
node.setOutsideBuildArea(True)
continue
- if node.collidesWithArea(self.getDisallowedAreas()):
+ if node.collidesWithAreas(self.getDisallowedAreas()):
+ node.setOutsideBuildArea(True)
+ continue
+ # If the entire node is below the build plate, still mark it as outside.
+ node_bounding_box = node.getBoundingBox()
+ if node_bounding_box and node_bounding_box.top < 0:
node.setOutsideBuildArea(True)
continue
-
# Mark the node as outside build volume if the set extruder is disabled
extruder_position = node.callDecoration("getActiveExtruderPosition")
- if extruder_position not in self._global_container_stack.extruders:
- continue
- if not self._global_container_stack.extruders[extruder_position].isEnabled:
- node.setOutsideBuildArea(True)
+ try:
+ if not self._global_container_stack.extruderList[int(extruder_position)].isEnabled:
+ node.setOutsideBuildArea(True)
+ continue
+ except IndexError:
continue
node.setOutsideBuildArea(False)
@@ -274,8 +288,8 @@ class BuildVolume(SceneNode):
child_node.setOutsideBuildArea(group_node.isOutsideBuildArea())
## Update the outsideBuildArea of a single node, given bounds or current build volume
- def checkBoundsAndUpdate(self, node: CuraSceneNode, bounds: Optional[AxisAlignedBox] = None):
- if not isinstance(node, CuraSceneNode):
+ def checkBoundsAndUpdate(self, node: CuraSceneNode, bounds: Optional[AxisAlignedBox] = None) -> None:
+ if not isinstance(node, CuraSceneNode) or self._global_container_stack is None:
return
if bounds is None:
@@ -295,44 +309,55 @@ class BuildVolume(SceneNode):
node.setOutsideBuildArea(True)
return
- if node.collidesWithArea(self.getDisallowedAreas()):
+ if node.collidesWithAreas(self.getDisallowedAreas()):
node.setOutsideBuildArea(True)
return
# Mark the node as outside build volume if the set extruder is disabled
extruder_position = node.callDecoration("getActiveExtruderPosition")
- if not self._global_container_stack.extruders[extruder_position].isEnabled:
+ if not self._global_container_stack.extruderList[int(extruder_position)].isEnabled:
node.setOutsideBuildArea(True)
return
node.setOutsideBuildArea(False)
- ## Recalculates the build volume & disallowed areas.
- def rebuild(self):
- if not self._width or not self._height or not self._depth:
- return
+ def _buildGridMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d:float, z_fight_distance: float) -> MeshData:
+ mb = MeshBuilder()
+ if self._shape != "elliptic":
+ # Build plate grid mesh
+ mb.addQuad(
+ Vector(min_w, min_h - z_fight_distance, min_d),
+ Vector(max_w, min_h - z_fight_distance, min_d),
+ Vector(max_w, min_h - z_fight_distance, max_d),
+ Vector(min_w, min_h - z_fight_distance, max_d)
+ )
- if not self._engine_ready:
- return
+ for n in range(0, 6):
+ v = mb.getVertex(n)
+ mb.setVertexUVCoordinates(n, v[0], v[2])
+ return mb.build()
+ else:
+ aspect = 1.0
+ scale_matrix = Matrix()
+ if self._width != 0:
+ # Scale circular meshes by aspect ratio if width != height
+ aspect = self._depth / self._width
+ scale_matrix.compose(scale=Vector(1, 1, aspect))
+ mb.addVertex(0, min_h - z_fight_distance, 0)
+ mb.addArc(max_w, Vector.Unit_Y, center=Vector(0, min_h - z_fight_distance, 0))
+ sections = mb.getVertexCount() - 1 # Center point is not an arc section
+ indices = []
+ for n in range(0, sections - 1):
+ indices.append([0, n + 2, n + 1])
+ mb.addIndices(numpy.asarray(indices, dtype=numpy.int32))
+ mb.calculateNormals()
- if not self._volume_outline_color:
- theme = self._application.getTheme()
- self._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
- self._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
- self._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
- self._z_axis_color = Color(*theme.getColor("z_axis").getRgb())
- self._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
- self._error_area_color = Color(*theme.getColor("error_area").getRgb())
-
- min_w = -self._width / 2
- max_w = self._width / 2
- min_h = 0.0
- max_h = self._height
- min_d = -self._depth / 2
- max_d = self._depth / 2
-
- z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting
+ for n in range(0, mb.getVertexCount()):
+ v = mb.getVertex(n)
+ mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
+ return mb.build().getTransformed(scale_matrix)
+ def _buildMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d:float, z_fight_distance: float) -> MeshData:
if self._shape != "elliptic":
# Outline 'cube' of the build volume
mb = MeshBuilder()
@@ -351,25 +376,10 @@ class BuildVolume(SceneNode):
mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self._volume_outline_color)
mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self._volume_outline_color)
- self.setMeshData(mb.build())
-
- # Build plate grid mesh
- mb = MeshBuilder()
- mb.addQuad(
- Vector(min_w, min_h - z_fight_distance, min_d),
- Vector(max_w, min_h - z_fight_distance, min_d),
- Vector(max_w, min_h - z_fight_distance, max_d),
- Vector(min_w, min_h - z_fight_distance, max_d)
- )
-
- for n in range(0, 6):
- v = mb.getVertex(n)
- mb.setVertexUVCoordinates(n, v[0], v[2])
- self._grid_mesh = mb.build()
+ return mb.build()
else:
# Bottom and top 'ellipse' of the build volume
- aspect = 1.0
scale_matrix = Matrix()
if self._width != 0:
# Scale circular meshes by aspect ratio if width != height
@@ -378,23 +388,119 @@ class BuildVolume(SceneNode):
mb = MeshBuilder()
mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self._volume_outline_color)
mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self._volume_outline_color)
- self.setMeshData(mb.build().getTransformed(scale_matrix))
+ return mb.build().getTransformed(scale_matrix)
- # Build plate grid mesh
- mb = MeshBuilder()
- mb.addVertex(0, min_h - z_fight_distance, 0)
- mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0))
- sections = mb.getVertexCount() - 1 # Center point is not an arc section
- indices = []
- for n in range(0, sections - 1):
- indices.append([0, n + 2, n + 1])
- mb.addIndices(numpy.asarray(indices, dtype = numpy.int32))
- mb.calculateNormals()
+ def _buildOriginMesh(self, origin: Vector) -> MeshData:
+ mb = MeshBuilder()
+ mb.addCube(
+ width=self._origin_line_length,
+ height=self._origin_line_width,
+ depth=self._origin_line_width,
+ center=origin + Vector(self._origin_line_length / 2, 0, 0),
+ color=self._x_axis_color
+ )
+ mb.addCube(
+ width=self._origin_line_width,
+ height=self._origin_line_length,
+ depth=self._origin_line_width,
+ center=origin + Vector(0, self._origin_line_length / 2, 0),
+ color=self._y_axis_color
+ )
+ mb.addCube(
+ width=self._origin_line_width,
+ height=self._origin_line_width,
+ depth=self._origin_line_length,
+ center=origin - Vector(0, 0, self._origin_line_length / 2),
+ color=self._z_axis_color
+ )
+ return mb.build()
- for n in range(0, mb.getVertexCount()):
- v = mb.getVertex(n)
- mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
- self._grid_mesh = mb.build().getTransformed(scale_matrix)
+ def _updateColors(self):
+ theme = self._application.getTheme()
+ if theme is None:
+ return
+ self._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
+ self._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
+ self._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
+ self._z_axis_color = Color(*theme.getColor("z_axis").getRgb())
+ self._disallowed_area_color = Color(*theme.getColor("disallowed_area").getRgb())
+ self._error_area_color = Color(*theme.getColor("error_area").getRgb())
+
+ def _buildErrorMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d: float, disallowed_area_height: float) -> Optional[MeshData]:
+ if not self._error_areas:
+ return None
+ mb = MeshBuilder()
+ for error_area in self._error_areas:
+ color = self._error_area_color
+ points = error_area.getPoints()
+ first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
+ self._clamp(points[0][1], min_d, max_d))
+ previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
+ self._clamp(points[0][1], min_d, max_d))
+ for point in points:
+ new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
+ self._clamp(point[1], min_d, max_d))
+ mb.addFace(first, previous_point, new_point, color=color)
+ previous_point = new_point
+ return mb.build()
+
+ def _buildDisallowedAreaMesh(self, min_w: float, max_w: float, min_h: float, max_h: float, min_d: float, max_d: float, disallowed_area_height: float) -> Optional[MeshData]:
+ if not self._disallowed_areas:
+ return None
+
+ mb = MeshBuilder()
+ color = self._disallowed_area_color
+ for polygon in self._disallowed_areas:
+ points = polygon.getPoints()
+ if len(points) == 0:
+ continue
+
+ first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
+ self._clamp(points[0][1], min_d, max_d))
+ previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
+ self._clamp(points[0][1], min_d, max_d))
+ for point in points:
+ new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
+ self._clamp(point[1], min_d, max_d))
+ mb.addFace(first, previous_point, new_point, color=color)
+ previous_point = new_point
+
+ # Find the largest disallowed area to exclude it from the maximum scale bounds.
+ # This is a very nasty hack. This pretty much only works for UM machines.
+ # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
+ if numpy.min(points[:,
+ 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
+ size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
+ else:
+ size = 0
+ self._disallowed_area_size = max(size, self._disallowed_area_size)
+ return mb.build()
+
+ ## Recalculates the build volume & disallowed areas.
+ def rebuild(self) -> None:
+ if not self._width or not self._height or not self._depth:
+ return
+
+ if not self._engine_ready:
+ return
+
+ if not self._global_container_stack:
+ return
+
+ if not self._volume_outline_color:
+ self._updateColors()
+
+ min_w = -self._width / 2
+ max_w = self._width / 2
+ min_h = 0.0
+ max_h = self._height
+ min_d = -self._depth / 2
+ max_d = self._depth / 2
+
+ z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting
+
+ self._grid_mesh = self._buildGridMesh(min_w, max_w, min_h, max_h, min_d, max_d, z_fight_distance)
+ self.setMeshData(self._buildMesh(min_w, max_w, min_h, max_h, min_d, max_d, z_fight_distance))
# Indication of the machine origin
if self._global_container_stack.getProperty("machine_center_is_zero", "value"):
@@ -402,77 +508,13 @@ class BuildVolume(SceneNode):
else:
origin = Vector(min_w, min_h, max_d)
- mb = MeshBuilder()
- mb.addCube(
- width = self._origin_line_length,
- height = self._origin_line_width,
- depth = self._origin_line_width,
- center = origin + Vector(self._origin_line_length / 2, 0, 0),
- color = self._x_axis_color
- )
- mb.addCube(
- width = self._origin_line_width,
- height = self._origin_line_length,
- depth = self._origin_line_width,
- center = origin + Vector(0, self._origin_line_length / 2, 0),
- color = self._y_axis_color
- )
- mb.addCube(
- width = self._origin_line_width,
- height = self._origin_line_width,
- depth = self._origin_line_length,
- center = origin - Vector(0, 0, self._origin_line_length / 2),
- color = self._z_axis_color
- )
- self._origin_mesh = mb.build()
+ self._origin_mesh = self._buildOriginMesh(origin)
disallowed_area_height = 0.1
- disallowed_area_size = 0
- if self._disallowed_areas:
- mb = MeshBuilder()
- color = self._disallowed_area_color
- for polygon in self._disallowed_areas:
- points = polygon.getPoints()
- if len(points) == 0:
- continue
+ self._disallowed_area_size = 0.
+ self._disallowed_area_mesh = self._buildDisallowedAreaMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height)
- first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
- previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
- for point in points:
- new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d))
- mb.addFace(first, previous_point, new_point, color = color)
- previous_point = new_point
-
- # Find the largest disallowed area to exclude it from the maximum scale bounds.
- # This is a very nasty hack. This pretty much only works for UM machines.
- # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
- if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
- size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
- else:
- size = 0
- disallowed_area_size = max(size, disallowed_area_size)
-
- self._disallowed_area_mesh = mb.build()
- else:
- self._disallowed_area_mesh = None
-
- if self._error_areas:
- mb = MeshBuilder()
- for error_area in self._error_areas:
- color = self._error_area_color
- points = error_area.getPoints()
- first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
- self._clamp(points[0][1], min_d, max_d))
- previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
- self._clamp(points[0][1], min_d, max_d))
- for point in points:
- new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
- self._clamp(point[1], min_d, max_d))
- mb.addFace(first, previous_point, new_point, color=color)
- previous_point = new_point
- self._error_mesh = mb.build()
- else:
- self._error_mesh = None
+ self._error_mesh = self._buildErrorMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height)
self._volume_aabb = AxisAlignedBox(
minimum = Vector(min_w, min_h - 1.0, min_d),
@@ -484,23 +526,26 @@ class BuildVolume(SceneNode):
# This is probably wrong in all other cases. TODO!
# The +1 and -1 is added as there is always a bit of extra room required to work properly.
scale_to_max_bounds = AxisAlignedBox(
- minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1),
- maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
+ minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + self._disallowed_area_size - bed_adhesion_size + 1),
+ maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - self._disallowed_area_size + bed_adhesion_size - 1)
)
- self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds
+ self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds # type: ignore
self.updateNodeBoundaryCheck()
- def getBoundingBox(self) -> AxisAlignedBox:
+ def getBoundingBox(self):
return self._volume_aabb
def getRaftThickness(self) -> float:
return self._raft_thickness
- def _updateRaftThickness(self):
+ def _updateRaftThickness(self) -> None:
+ if not self._global_container_stack:
+ return
+
old_raft_thickness = self._raft_thickness
- if self._global_container_stack.extruders:
+ if self._global_container_stack.extruderList:
# This might be called before the extruder stacks have initialised, in which case getting the adhesion_type fails
self._adhesion_type = self._global_container_stack.getProperty("adhesion_type", "value")
self._raft_thickness = 0.0
@@ -509,7 +554,7 @@ class BuildVolume(SceneNode):
self._global_container_stack.getProperty("raft_base_thickness", "value") +
self._global_container_stack.getProperty("raft_interface_thickness", "value") +
self._global_container_stack.getProperty("raft_surface_layers", "value") *
- self._global_container_stack.getProperty("raft_surface_thickness", "value") +
+ self._global_container_stack.getProperty("raft_surface_thickness", "value") +
self._global_container_stack.getProperty("raft_airgap", "value") -
self._global_container_stack.getProperty("layer_0_z_overlap", "value"))
@@ -518,28 +563,23 @@ class BuildVolume(SceneNode):
self.setPosition(Vector(0, -self._raft_thickness, 0), SceneNode.TransformSpace.World)
self.raftThicknessChanged.emit()
- def _updateExtraZClearance(self) -> None:
+ def _calculateExtraZClearance(self, extruders: List["ContainerStack"]) -> float:
+ if not self._global_container_stack:
+ return 0
+
extra_z = 0.0
- extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
- use_extruders = False
for extruder in extruders:
if extruder.getProperty("retraction_hop_enabled", "value"):
retraction_hop = extruder.getProperty("retraction_hop", "value")
if extra_z is None or retraction_hop > extra_z:
extra_z = retraction_hop
- use_extruders = True
- if not use_extruders:
- # If no extruders, take global value.
- if self._global_container_stack.getProperty("retraction_hop_enabled", "value"):
- extra_z = self._global_container_stack.getProperty("retraction_hop", "value")
- if extra_z != self._extra_z_clearance:
- self._extra_z_clearance = extra_z
+ return extra_z
def _onStackChanged(self):
self._stack_change_timer.start()
## Update the build volume visualization
- def _onStackChangeTimerFinished(self):
+ def _onStackChangeTimerFinished(self) -> None:
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
@@ -570,7 +610,7 @@ class BuildVolume(SceneNode):
self._updateDisallowedAreas()
self._updateRaftThickness()
- self._updateExtraZClearance()
+ self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
if self._engine_ready:
self.rebuild()
@@ -579,20 +619,23 @@ class BuildVolume(SceneNode):
if camera:
diagonal = self.getDiagonalSize()
if diagonal > 1:
- camera.setZoomRange(min = 0.1, max = diagonal * 5) #You can zoom out up to 5 times the diagonal. This gives some space around the volume.
+ # You can zoom out up to 5 times the diagonal. This gives some space around the volume.
+ camera.setZoomRange(min = 0.1, max = diagonal * 5) # type: ignore
- def _onEngineCreated(self):
+ def _onEngineCreated(self) -> None:
self._engine_ready = True
self.rebuild()
- def _onSettingChangeTimerFinished(self):
+ def _onSettingChangeTimerFinished(self) -> None:
+ if not self._global_container_stack:
+ return
+
rebuild_me = False
update_disallowed_areas = False
update_raft_thickness = False
update_extra_z_clearance = True
for setting_key in self._changed_settings_since_last_rebuild:
-
if setting_key == "print_sequence":
machine_height = self._global_container_stack.getProperty("machine_height", "value")
if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
@@ -605,33 +648,26 @@ class BuildVolume(SceneNode):
self._height = self._global_container_stack.getProperty("machine_height", "value")
self._build_volume_message.hide()
update_disallowed_areas = True
- rebuild_me = True
# sometimes the machine size or shape settings are adjusted on the active machine, we should reflect this
if setting_key in self._machine_settings:
- self._height = self._global_container_stack.getProperty("machine_height", "value")
- self._width = self._global_container_stack.getProperty("machine_width", "value")
- self._depth = self._global_container_stack.getProperty("machine_depth", "value")
- self._shape = self._global_container_stack.getProperty("machine_shape", "value")
+ self._updateMachineSizeProperties()
update_extra_z_clearance = True
update_disallowed_areas = True
- rebuild_me = True
- if setting_key in self._skirt_settings + self._prime_settings + self._tower_settings + self._ooze_shield_settings + self._distance_settings + self._extruder_settings:
+ if setting_key in self._disallowed_area_settings:
update_disallowed_areas = True
- rebuild_me = True
if setting_key in self._raft_settings:
update_raft_thickness = True
- rebuild_me = True
if setting_key in self._extra_z_settings:
update_extra_z_clearance = True
- rebuild_me = True
if setting_key in self._limit_to_extruder_settings:
update_disallowed_areas = True
- rebuild_me = True
+
+ rebuild_me = update_extra_z_clearance or update_disallowed_areas or update_raft_thickness
# We only want to update all of them once.
if update_disallowed_areas:
@@ -641,7 +677,7 @@ class BuildVolume(SceneNode):
self._updateRaftThickness()
if update_extra_z_clearance:
- self._updateExtraZClearance()
+ self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
if rebuild_me:
self.rebuild()
@@ -649,7 +685,7 @@ class BuildVolume(SceneNode):
# We just did a rebuild, reset the list.
self._changed_settings_since_last_rebuild = []
- def _onSettingPropertyChanged(self, setting_key: str, property_name: str):
+ def _onSettingPropertyChanged(self, setting_key: str, property_name: str) -> None:
if property_name != "value":
return
@@ -660,6 +696,14 @@ class BuildVolume(SceneNode):
def hasErrors(self) -> bool:
return self._has_errors
+ def _updateMachineSizeProperties(self) -> None:
+ if not self._global_container_stack:
+ return
+ self._height = self._global_container_stack.getProperty("machine_height", "value")
+ self._width = self._global_container_stack.getProperty("machine_width", "value")
+ self._depth = self._global_container_stack.getProperty("machine_depth", "value")
+ self._shape = self._global_container_stack.getProperty("machine_shape", "value")
+
## Calls _updateDisallowedAreas and makes sure the changes appear in the
# scene.
#
@@ -671,57 +715,26 @@ class BuildVolume(SceneNode):
def _updateDisallowedAreasAndRebuild(self):
self._updateDisallowedAreas()
self._updateRaftThickness()
- self._updateExtraZClearance()
+ self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
self.rebuild()
- def _updateDisallowedAreas(self):
+ def _updateDisallowedAreas(self) -> None:
if not self._global_container_stack:
return
self._error_areas = []
- extruder_manager = ExtruderManager.getInstance()
- used_extruders = extruder_manager.getUsedExtruderStacks()
+ used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
disallowed_border_size = self.getEdgeDisallowedSize()
- if not used_extruders:
- # If no extruder is used, assume that the active extruder is used (else nothing is drawn)
- if extruder_manager.getActiveExtruderStack():
- used_extruders = [extruder_manager.getActiveExtruderStack()]
- else:
- used_extruders = [self._global_container_stack]
-
- result_areas = self._computeDisallowedAreasStatic(disallowed_border_size, used_extruders) #Normal machine disallowed areas can always be added.
+ result_areas = self._computeDisallowedAreasStatic(disallowed_border_size, used_extruders) # Normal machine disallowed areas can always be added.
prime_areas = self._computeDisallowedAreasPrimeBlob(disallowed_border_size, used_extruders)
- result_areas_no_brim = self._computeDisallowedAreasStatic(0, used_extruders) #Where the priming is not allowed to happen. This is not added to the result, just for collision checking.
- prime_disallowed_areas = copy.deepcopy(result_areas_no_brim)
+ result_areas_no_brim = self._computeDisallowedAreasStatic(0, used_extruders) # Where the priming is not allowed to happen. This is not added to the result, just for collision checking.
- #Check if prime positions intersect with disallowed areas.
+ # Check if prime positions intersect with disallowed areas.
for extruder in used_extruders:
extruder_id = extruder.getId()
- collision = False
- for prime_polygon in prime_areas[extruder_id]:
- for disallowed_polygon in prime_disallowed_areas[extruder_id]:
- if prime_polygon.intersectsPolygon(disallowed_polygon) is not None:
- collision = True
- break
- if collision:
- break
-
- #Also check other prime positions (without additional offset).
- for other_extruder_id in prime_areas:
- if extruder_id == other_extruder_id: #It is allowed to collide with itself.
- continue
- for other_prime_polygon in prime_areas[other_extruder_id]:
- if prime_polygon.intersectsPolygon(other_prime_polygon):
- collision = True
- break
- if collision:
- break
- if collision:
- break
-
result_areas[extruder_id].extend(prime_areas[extruder_id])
result_areas_no_brim[extruder_id].extend(prime_areas[extruder_id])
@@ -729,33 +742,28 @@ class BuildVolume(SceneNode):
for area in nozzle_disallowed_areas:
polygon = Polygon(numpy.array(area, numpy.float32))
polygon_disallowed_border = polygon.getMinkowskiHull(Polygon.approximatedCircle(disallowed_border_size))
- result_areas[extruder_id].append(polygon_disallowed_border) #Don't perform the offset on these.
- #polygon_minimal_border = polygon.getMinkowskiHull(5)
- result_areas_no_brim[extruder_id].append(polygon) # no brim
+ result_areas[extruder_id].append(polygon_disallowed_border) # Don't perform the offset on these.
+ result_areas_no_brim[extruder_id].append(polygon) # No brim
# Add prime tower location as disallowed area.
- if len(used_extruders) > 1: #No prime tower in single-extrusion.
-
- if len([x for x in used_extruders if x.isEnabled == True]) > 1: #No prime tower if only one extruder is enabled
- prime_tower_collision = False
- prime_tower_areas = self._computeDisallowedAreasPrinted(used_extruders)
- for extruder_id in prime_tower_areas:
- for i_area, prime_tower_area in enumerate(prime_tower_areas[extruder_id]):
- for area in result_areas[extruder_id]:
- if prime_tower_area.intersectsPolygon(area) is not None:
- prime_tower_collision = True
- break
- if prime_tower_collision: #Already found a collision.
+ if len([x for x in used_extruders if x.isEnabled]) > 1: # No prime tower if only one extruder is enabled
+ prime_tower_collision = False
+ prime_tower_areas = self._computeDisallowedAreasPrinted(used_extruders)
+ for extruder_id in prime_tower_areas:
+ for area_index, prime_tower_area in enumerate(prime_tower_areas[extruder_id]):
+ for area in result_areas[extruder_id]:
+ if prime_tower_area.intersectsPolygon(area) is not None:
+ prime_tower_collision = True
break
- if (ExtruderManager.getInstance().getResolveOrValue("prime_tower_brim_enable") and
- ExtruderManager.getInstance().getResolveOrValue("adhesion_type") != "raft"):
- prime_tower_areas[extruder_id][i_area] = prime_tower_area.getMinkowskiHull(
- Polygon.approximatedCircle(disallowed_border_size))
- if not prime_tower_collision:
- result_areas[extruder_id].extend(prime_tower_areas[extruder_id])
- result_areas_no_brim[extruder_id].extend(prime_tower_areas[extruder_id])
- else:
- self._error_areas.extend(prime_tower_areas[extruder_id])
+ if prime_tower_collision: # Already found a collision.
+ break
+ if self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and self._global_container_stack.getProperty("adhesion_type", "value") != "raft":
+ prime_tower_areas[extruder_id][area_index] = prime_tower_area.getMinkowskiHull(Polygon.approximatedCircle(disallowed_border_size))
+ if not prime_tower_collision:
+ result_areas[extruder_id].extend(prime_tower_areas[extruder_id])
+ result_areas_no_brim[extruder_id].extend(prime_tower_areas[extruder_id])
+ else:
+ self._error_areas.extend(prime_tower_areas[extruder_id])
self._has_errors = len(self._error_areas) > 0
@@ -776,11 +784,14 @@ class BuildVolume(SceneNode):
# where that extruder may not print.
def _computeDisallowedAreasPrinted(self, used_extruders):
result = {}
+ adhesion_extruder = None #type: ExtruderStack
for extruder in used_extruders:
+ if int(extruder.getProperty("extruder_nr", "value")) == int(self._global_container_stack.getProperty("adhesion_extruder_nr", "value")):
+ adhesion_extruder = extruder
result[extruder.getId()] = []
- #Currently, the only normally printed object is the prime tower.
- if ExtruderManager.getInstance().getResolveOrValue("prime_tower_enable"):
+ # Currently, the only normally printed object is the prime tower.
+ if self._global_container_stack.getProperty("prime_tower_enable", "value"):
prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value")
machine_width = self._global_container_stack.getProperty("machine_width", "value")
machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
@@ -790,27 +801,19 @@ class BuildVolume(SceneNode):
prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
prime_tower_y = prime_tower_y + machine_depth / 2
- if (ExtruderManager.getInstance().getResolveOrValue("prime_tower_brim_enable") and
- ExtruderManager.getInstance().getResolveOrValue("adhesion_type") != "raft"):
+ if adhesion_extruder is not None and self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and self._global_container_stack.getProperty("adhesion_type", "value") != "raft":
brim_size = (
- extruder.getProperty("brim_line_count", "value") *
- extruder.getProperty("skirt_brim_line_width", "value") / 100.0 *
- extruder.getProperty("initial_layer_line_width_factor", "value")
+ adhesion_extruder.getProperty("brim_line_count", "value") *
+ adhesion_extruder.getProperty("skirt_brim_line_width", "value") / 100.0 *
+ adhesion_extruder.getProperty("initial_layer_line_width_factor", "value")
)
prime_tower_x -= brim_size
prime_tower_y += brim_size
- if self._global_container_stack.getProperty("prime_tower_circular", "value"):
- radius = prime_tower_size / 2
- prime_tower_area = Polygon.approximatedCircle(radius)
- prime_tower_area = prime_tower_area.translate(prime_tower_x - radius, prime_tower_y - radius)
- else:
- prime_tower_area = Polygon([
- [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size],
- [prime_tower_x, prime_tower_y - prime_tower_size],
- [prime_tower_x, prime_tower_y],
- [prime_tower_x - prime_tower_size, prime_tower_y],
- ])
+ radius = prime_tower_size / 2
+ prime_tower_area = Polygon.approximatedCircle(radius)
+ prime_tower_area = prime_tower_area.translate(prime_tower_x - radius, prime_tower_y - radius)
+
prime_tower_area = prime_tower_area.getMinkowskiHull(Polygon.approximatedCircle(0))
for extruder in used_extruders:
result[extruder.getId()].append(prime_tower_area) #The prime tower location is the same for each extruder, regardless of offset.
@@ -828,9 +831,10 @@ class BuildVolume(SceneNode):
# \param used_extruders The extruder stacks to generate disallowed areas
# for.
# \return A dictionary with for each used extruder ID the prime areas.
- def _computeDisallowedAreasPrimeBlob(self, border_size, used_extruders):
- result = {}
-
+ def _computeDisallowedAreasPrimeBlob(self, border_size: float, used_extruders: List["ExtruderStack"]) -> Dict[str, List[Polygon]]:
+ result = {} # type: Dict[str, List[Polygon]]
+ if not self._global_container_stack:
+ return result
machine_width = self._global_container_stack.getProperty("machine_width", "value")
machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
for extruder in used_extruders:
@@ -838,13 +842,13 @@ class BuildVolume(SceneNode):
prime_x = extruder.getProperty("extruder_prime_pos_x", "value")
prime_y = -extruder.getProperty("extruder_prime_pos_y", "value")
- #Ignore extruder prime position if it is not set or if blob is disabled
+ # Ignore extruder prime position if it is not set or if blob is disabled
if (prime_x == 0 and prime_y == 0) or not prime_blob_enabled:
result[extruder.getId()] = []
continue
if not self._global_container_stack.getProperty("machine_center_is_zero", "value"):
- prime_x = prime_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
+ prime_x = prime_x - machine_width / 2 # Offset by half machine_width and _depth to put the origin in the front-left.
prime_y = prime_y + machine_depth / 2
prime_polygon = Polygon.approximatedCircle(PRIME_CLEARANCE)
@@ -867,9 +871,12 @@ class BuildVolume(SceneNode):
# for.
# \return A dictionary with for each used extruder ID the disallowed areas
# where that extruder may not print.
- def _computeDisallowedAreasStatic(self, border_size, used_extruders):
- #Convert disallowed areas to polygons and dilate them.
+ def _computeDisallowedAreasStatic(self, border_size:float, used_extruders: List["ExtruderStack"]) -> Dict[str, List[Polygon]]:
+ # Convert disallowed areas to polygons and dilate them.
machine_disallowed_polygons = []
+ if self._global_container_stack is None:
+ return {}
+
for area in self._global_container_stack.getProperty("machine_disallowed_areas", "value"):
polygon = Polygon(numpy.array(area, numpy.float32))
polygon = polygon.getMinkowskiHull(Polygon.approximatedCircle(border_size))
@@ -880,7 +887,7 @@ class BuildVolume(SceneNode):
nozzle_offsetting_for_disallowed_areas = self._global_container_stack.getMetaDataEntry(
"nozzle_offsetting_for_disallowed_areas", True)
- result = {}
+ result = {} # type: Dict[str, List[Polygon]]
for extruder in used_extruders:
extruder_id = extruder.getId()
offset_x = extruder.getProperty("machine_nozzle_offset_x", "value")
@@ -889,13 +896,13 @@ class BuildVolume(SceneNode):
offset_y = extruder.getProperty("machine_nozzle_offset_y", "value")
if offset_y is None:
offset_y = 0
- offset_y = -offset_y #Y direction of g-code is the inverse of Y direction of Cura's scene space.
+ offset_y = -offset_y # Y direction of g-code is the inverse of Y direction of Cura's scene space.
result[extruder_id] = []
for polygon in machine_disallowed_polygons:
- result[extruder_id].append(polygon.translate(offset_x, offset_y)) #Compensate for the nozzle offset of this extruder.
+ result[extruder_id].append(polygon.translate(offset_x, offset_y)) # Compensate for the nozzle offset of this extruder.
- #Add the border around the edge of the build volume.
+ # Add the border around the edge of the build volume.
left_unreachable_border = 0
right_unreachable_border = 0
top_unreachable_border = 0
@@ -903,7 +910,8 @@ class BuildVolume(SceneNode):
# Only do nozzle offsetting if needed
if nozzle_offsetting_for_disallowed_areas:
- #The build volume is defined as the union of the area that all extruders can reach, so we need to know the relative offset to all extruders.
+ # The build volume is defined as the union of the area that all extruders can reach, so we need to know
+ # the relative offset to all extruders.
for other_extruder in ExtruderManager.getInstance().getActiveExtruderStacks():
other_offset_x = other_extruder.getProperty("machine_nozzle_offset_x", "value")
if other_offset_x is None:
@@ -987,8 +995,8 @@ class BuildVolume(SceneNode):
[ half_machine_width - border_size, 0]
], numpy.float32)))
result[extruder_id].append(Polygon(numpy.array([
- [ half_machine_width,-half_machine_depth],
- [-half_machine_width,-half_machine_depth],
+ [ half_machine_width, -half_machine_depth],
+ [-half_machine_width, -half_machine_depth],
[ 0, -half_machine_depth + border_size]
], numpy.float32)))
@@ -1000,48 +1008,24 @@ class BuildVolume(SceneNode):
# stack.
#
# \return A sequence of setting values, one for each extruder.
- def _getSettingFromAllExtruders(self, setting_key):
+ def _getSettingFromAllExtruders(self, setting_key: str) -> List[Any]:
all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "value")
all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type")
- for i in range(len(all_values)):
- if not all_values[i] and (all_types[i] == "int" or all_types[i] == "float"):
+ for i, (setting_value, setting_type) in enumerate(zip(all_values, all_types)):
+ if not setting_value and (setting_type == "int" or setting_type == "float"):
all_values[i] = 0
return all_values
- ## Calculate the disallowed radius around the edge.
- #
- # This disallowed radius is to allow for space around the models that is
- # not part of the collision radius, such as bed adhesion (skirt/brim/raft)
- # and travel avoid distance.
- def getEdgeDisallowedSize(self):
- if not self._global_container_stack or not self._global_container_stack.extruders:
- return 0
+ def _calculateBedAdhesionSize(self, used_extruders):
+ if self._global_container_stack is None:
+ return
container_stack = self._global_container_stack
- used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
-
- # If we are printing one at a time, we need to add the bed adhesion size to the disallowed areas of the objects
- if container_stack.getProperty("print_sequence", "value") == "one_at_a_time":
- return 0.1 # Return a very small value, so we do draw disallowed area's near the edges.
-
adhesion_type = container_stack.getProperty("adhesion_type", "value")
skirt_brim_line_width = self._global_container_stack.getProperty("skirt_brim_line_width", "value")
initial_layer_line_width_factor = self._global_container_stack.getProperty("initial_layer_line_width_factor", "value")
- if adhesion_type == "skirt":
- skirt_distance = self._global_container_stack.getProperty("skirt_gap", "value")
- skirt_line_count = self._global_container_stack.getProperty("skirt_line_count", "value")
-
- bed_adhesion_size = skirt_distance + (skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0
-
- for extruder_stack in used_extruders:
- bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0
-
- # We don't create an additional line for the extruder we're printing the skirt with.
- bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
-
- elif (adhesion_type == "brim" or
- (self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and
- self._global_container_stack.getProperty("adhesion_type", "value") != "raft")):
+ # Use brim width if brim is enabled OR the prime tower has a brim.
+ if adhesion_type == "brim" or (self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and adhesion_type != "raft"):
brim_line_count = self._global_container_stack.getProperty("brim_line_count", "value")
bed_adhesion_size = skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0
@@ -1050,13 +1034,22 @@ class BuildVolume(SceneNode):
# We don't create an additional line for the extruder we're printing the brim with.
bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
+ elif adhesion_type == "skirt": # No brim? Also not on prime tower? Then use whatever the adhesion type is saying: Skirt, raft or none.
+ skirt_distance = self._global_container_stack.getProperty("skirt_gap", "value")
+ skirt_line_count = self._global_container_stack.getProperty("skirt_line_count", "value")
+ bed_adhesion_size = skirt_distance + (
+ skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0
+
+ for extruder_stack in used_extruders:
+ bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0
+
+ # We don't create an additional line for the extruder we're printing the skirt with.
+ bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
elif adhesion_type == "raft":
bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value")
-
elif adhesion_type == "none":
bed_adhesion_size = 0
-
else:
raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?")
@@ -1065,26 +1058,56 @@ class BuildVolume(SceneNode):
self._global_container_stack.getProperty("machine_depth", "value")
)
bed_adhesion_size = min(bed_adhesion_size, max_length_available)
+ return bed_adhesion_size
+ def _calculateFarthestShieldDistance(self, container_stack):
+ farthest_shield_distance = 0
+ if container_stack.getProperty("draft_shield_enabled", "value"):
+ farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("draft_shield_dist", "value"))
+ if container_stack.getProperty("ooze_shield_enabled", "value"):
+ farthest_shield_distance = max(farthest_shield_distance,container_stack.getProperty("ooze_shield_dist", "value"))
+ return farthest_shield_distance
+
+ def _calculateSupportExpansion(self, container_stack):
support_expansion = 0
support_enabled = self._global_container_stack.getProperty("support_enable", "value")
support_offset = self._global_container_stack.getProperty("support_offset", "value")
if support_enabled and support_offset:
support_expansion += support_offset
+ return support_expansion
- farthest_shield_distance = 0
- if container_stack.getProperty("draft_shield_enabled", "value"):
- farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("draft_shield_dist", "value"))
- if container_stack.getProperty("ooze_shield_enabled", "value"):
- farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("ooze_shield_dist", "value"))
-
+ def _calculateMoveFromWallRadius(self, used_extruders):
move_from_wall_radius = 0 # Moves that start from outer wall.
- move_from_wall_radius = max(move_from_wall_radius, max(self._getSettingFromAllExtruders("infill_wipe_dist")))
- avoid_enabled_per_extruder = [stack.getProperty("travel_avoid_other_parts","value") for stack in used_extruders]
+ all_values = [move_from_wall_radius]
+ all_values.extend(self._getSettingFromAllExtruders("infill_wipe_dist"))
+ move_from_wall_radius = max(all_values)
+ avoid_enabled_per_extruder = [stack.getProperty("travel_avoid_other_parts", "value") for stack in used_extruders]
travel_avoid_distance_per_extruder = [stack.getProperty("travel_avoid_distance", "value") for stack in used_extruders]
- for avoid_other_parts_enabled, avoid_distance in zip(avoid_enabled_per_extruder, travel_avoid_distance_per_extruder): #For each extruder (or just global).
+ for avoid_other_parts_enabled, avoid_distance in zip(avoid_enabled_per_extruder, travel_avoid_distance_per_extruder): # For each extruder (or just global).
if avoid_other_parts_enabled:
move_from_wall_radius = max(move_from_wall_radius, avoid_distance)
+ return move_from_wall_radius
+
+ ## Calculate the disallowed radius around the edge.
+ #
+ # This disallowed radius is to allow for space around the models that is
+ # not part of the collision radius, such as bed adhesion (skirt/brim/raft)
+ # and travel avoid distance.
+ def getEdgeDisallowedSize(self):
+ if not self._global_container_stack or not self._global_container_stack.extruderList:
+ return 0
+
+ container_stack = self._global_container_stack
+ used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
+
+ # If we are printing one at a time, we need to add the bed adhesion size to the disallowed areas of the objects
+ if container_stack.getProperty("print_sequence", "value") == "one_at_a_time":
+ return 0.1
+
+ bed_adhesion_size = self._calculateBedAdhesionSize(used_extruders)
+ support_expansion = self._calculateSupportExpansion(self._global_container_stack)
+ farthest_shield_distance = self._calculateFarthestShieldDistance(self._global_container_stack)
+ move_from_wall_radius = self._calculateMoveFromWallRadius(used_extruders)
# Now combine our different pieces of data to get the final border size.
# Support expansion is added to the bed adhesion, since the bed adhesion goes around support.
@@ -1100,8 +1123,9 @@ class BuildVolume(SceneNode):
_raft_settings = ["adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap", "layer_0_z_overlap"]
_extra_z_settings = ["retraction_hop_enabled", "retraction_hop"]
_prime_settings = ["extruder_prime_pos_x", "extruder_prime_pos_y", "extruder_prime_pos_z", "prime_blob_enable"]
- _tower_settings = ["prime_tower_enable", "prime_tower_circular", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y", "prime_tower_brim_enable"]
+ _tower_settings = ["prime_tower_enable", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y", "prime_tower_brim_enable"]
_ooze_shield_settings = ["ooze_shield_enabled", "ooze_shield_dist"]
_distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports"]
_extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.
_limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "adhesion_extruder_nr"]
+ _disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings
diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py
index d43743bc37..1ec00787d7 100644
--- a/cura/CrashHandler.py
+++ b/cura/CrashHandler.py
@@ -12,9 +12,10 @@ import json
import ssl
import urllib.request
import urllib.error
-import shutil
-from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, Qt, QUrl
+import certifi
+
+from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QUrl
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QCheckBox, QPushButton
from PyQt5.QtGui import QDesktopServices
@@ -22,9 +23,10 @@ from UM.Application import Application
from UM.Logger import Logger
from UM.View.GL.OpenGL import OpenGL
from UM.i18n import i18nCatalog
-from UM.Platform import Platform
from UM.Resources import Resources
+from cura import ApplicationMetadata
+
catalog = i18nCatalog("cura")
MYPY = False
@@ -181,6 +183,7 @@ class CrashHandler:
self.cura_version = catalog.i18nc("@label unknown version of Cura", "Unknown")
crash_info = "" + catalog.i18nc("@label Cura version number", "Cura version") + ": " + str(self.cura_version) + " "
+ crash_info += "" + catalog.i18nc("@label Cura build type", "Cura build type") + ": " + str(ApplicationMetadata.CuraBuildType) + " "
crash_info += "" + catalog.i18nc("@label Type of platform", "Platform") + ": " + str(platform.platform()) + " "
crash_info += "" + catalog.i18nc("@label", "Qt version") + ": " + str(QT_VERSION_STR) + " "
crash_info += "" + catalog.i18nc("@label", "PyQt version") + ": " + str(PYQT_VERSION_STR) + " "
@@ -191,6 +194,7 @@ class CrashHandler:
group.setLayout(layout)
self.data["cura_version"] = self.cura_version
+ self.data["cura_build_type"] = ApplicationMetadata.CuraBuildType
self.data["os"] = {"type": platform.system(), "version": platform.version()}
self.data["qt_version"] = QT_VERSION_STR
self.data["pyqt_version"] = PYQT_VERSION_STR
@@ -319,7 +323,8 @@ class CrashHandler:
def _userDescriptionWidget(self):
group = QGroupBox()
- group.setTitle(catalog.i18nc("@title:groupbox", "User description"))
+ group.setTitle(catalog.i18nc("@title:groupbox", "User description" +
+ " (Note: Developers may not speak your language, please use English if possible)"))
layout = QVBoxLayout()
# When sending the report, the user comments will be collected
@@ -351,11 +356,13 @@ class CrashHandler:
# Convert data to bytes
binary_data = json.dumps(self.data).encode("utf-8")
+ # CURA-6698 Create an SSL context and use certifi CA certificates for verification.
+ context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2)
+ context.load_verify_locations(cafile = certifi.where())
# Submit data
- kwoptions = {"data": binary_data, "timeout": 5}
-
- if Platform.isOSX():
- kwoptions["context"] = ssl._create_unverified_context()
+ kwoptions = {"data": binary_data,
+ "timeout": 5,
+ "context": context}
Logger.log("i", "Sending crash report info to [%s]...", self.crash_url)
if not self.has_started:
diff --git a/cura/CuraActions.py b/cura/CuraActions.py
index 91e0966fed..b92abbe706 100644
--- a/cura/CuraActions.py
+++ b/cura/CuraActions.py
@@ -3,15 +3,17 @@
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtGui import QDesktopServices
-from typing import List, TYPE_CHECKING, cast
+from typing import List, Optional, cast
from UM.Event import CallFunctionEvent
from UM.FlameProfiler import pyqtSlot
+from UM.Math.Quaternion import Quaternion
from UM.Math.Vector import Vector
from UM.Scene.Selection import Selection
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
+from UM.Operations.RotateOperation import RotateOperation
from UM.Operations.TranslateOperation import TranslateOperation
import cura.CuraApplication
@@ -23,9 +25,8 @@ from cura.Settings.ExtruderManager import ExtruderManager
from cura.Operations.SetBuildPlateNumberOperation import SetBuildPlateNumberOperation
from UM.Logger import Logger
+from UM.Scene.SceneNode import SceneNode
-if TYPE_CHECKING:
- from UM.Scene.SceneNode import SceneNode
class CuraActions(QObject):
def __init__(self, parent: QObject = None) -> None:
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index 4d3d2434ff..ef5f987b85 100755
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.py
@@ -13,119 +13,130 @@ from PyQt5.QtGui import QColor, QIcon
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
+from UM.i18n import i18nCatalog
from UM.Application import Application
+from UM.Decorators import override, deprecated
+from UM.FlameProfiler import pyqtSlot
+from UM.Logger import Logger
+from UM.Message import Message
+from UM.Platform import Platform
from UM.PluginError import PluginNotFoundError
-from UM.Scene.SceneNode import SceneNode
-from UM.Scene.Camera import Camera
-from UM.Math.Vector import Vector
-from UM.Math.Quaternion import Quaternion
+from UM.Resources import Resources
+from UM.Preferences import Preferences
+from UM.Qt.QtApplication import QtApplication # The class we're inheriting from.
+import UM.Util
+from UM.View.SelectionPass import SelectionPass # For typing.
+
from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Math.Matrix import Matrix
-from UM.Platform import Platform
-from UM.Resources import Resources
-from UM.Scene.ToolHandle import ToolHandle
-from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+from UM.Math.Quaternion import Quaternion
+from UM.Math.Vector import Vector
+
from UM.Mesh.ReadMeshJob import ReadMeshJob
-from UM.Logger import Logger
-from UM.Preferences import Preferences
-from UM.Qt.QtApplication import QtApplication #The class we're inheriting from.
-from UM.View.SelectionPass import SelectionPass #For typing.
-from UM.Scene.Selection import Selection
-from UM.Scene.GroupDecorator import GroupDecorator
-from UM.Settings.ContainerStack import ContainerStack
-from UM.Settings.InstanceContainer import InstanceContainer
-from UM.Settings.Validator import Validator
-from UM.Message import Message
-from UM.i18n import i18nCatalog
-from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.SetTransformOperation import SetTransformOperation
+from UM.Scene.Camera import Camera
+from UM.Scene.GroupDecorator import GroupDecorator
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+from UM.Scene.SceneNode import SceneNode
+from UM.Scene.Selection import Selection
+from UM.Scene.ToolHandle import ToolHandle
+
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Settings.InstanceContainer import InstanceContainer
+from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType
+from UM.Settings.SettingFunction import SettingFunction
+from UM.Settings.Validator import Validator
+
+from UM.Workspace.WorkspaceReader import WorkspaceReader
+
from cura.API import CuraAPI
+
from cura.Arranging.Arrange import Arrange
from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob
from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob
from cura.Arranging.ShapeArray import ShapeArray
-from cura.MultiplyObjectsJob import MultiplyObjectsJob
-from cura.GlobalStacksModel import GlobalStacksModel
-from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
+
from cura.Operations.SetParentOperation import SetParentOperation
-from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
+
from cura.Scene.BlockSlicingDecorator import BlockSlicingDecorator
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
-from cura.Scene.CuraSceneNode import CuraSceneNode
-
+from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
from cura.Scene.CuraSceneController import CuraSceneController
+from cura.Scene.CuraSceneNode import CuraSceneNode
+from cura.Scene.GCodeListDecorator import GCodeListDecorator
+from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
+from cura.Scene import ZOffsetDecorator
-from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.SettingFunction import SettingFunction
-from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
-from cura.Settings.MachineNameValidator import MachineNameValidator
-
-from cura.Machines.Models.BuildPlateModel import BuildPlateModel
-from cura.Machines.Models.NozzleModel import NozzleModel
-from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel
-from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel
-from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
-from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel
-from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
-from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel
-from cura.Machines.Models.QualityManagementModel import QualityManagementModel
-from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel
-from cura.Machines.Models.MachineManagementModel import MachineManagementModel
-
-from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel
-
+from cura.Machines.ContainerTree import ContainerTree
from cura.Machines.MachineErrorChecker import MachineErrorChecker
+from cura.Machines.Models.BuildPlateModel import BuildPlateModel
+from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel
+from cura.Machines.Models.DiscoveredPrintersModel import DiscoveredPrintersModel
+from cura.Machines.Models.ExtrudersModel import ExtrudersModel
+from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel
+from cura.Machines.Models.FirstStartMachineActionsModel import FirstStartMachineActionsModel
+from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
+from cura.Machines.Models.GlobalStacksModel import GlobalStacksModel
+from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel
+from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel
+from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
+from cura.Machines.Models.NozzleModel import NozzleModel
+from cura.Machines.Models.QualityManagementModel import QualityManagementModel
+from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel
+from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel
+from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel
+from cura.Machines.Models.UserChangesModel import UserChangesModel
+from cura.Machines.Models.IntentModel import IntentModel
+from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel
+
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
+
+import cura.Settings.cura_empty_instance_containers
+from cura.Settings.ContainerManager import ContainerManager
+from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
+from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
+from cura.Settings.ExtruderManager import ExtruderManager
+from cura.Settings.ExtruderStack import ExtruderStack
+from cura.Settings.MachineManager import MachineManager
+from cura.Settings.MachineNameValidator import MachineNameValidator
+from cura.Settings.IntentManager import IntentManager
+from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
from cura.Settings.SettingInheritanceManager import SettingInheritanceManager
+from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel
from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager
-from cura.Machines.VariantManager import VariantManager
+from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager
+
+from cura.UI import CuraSplashScreen, MachineActionManager, PrintInformation
+from cura.UI.MachineSettingsManager import MachineSettingsManager
+from cura.UI.ObjectsModel import ObjectsModel
+from cura.UI.TextManager import TextManager
+from cura.UI.AddPrinterPagesModel import AddPrinterPagesModel
+from cura.UI.RecommendedMode import RecommendedMode
+from cura.UI.WelcomePagesModel import WelcomePagesModel
+from cura.UI.WhatsNewPagesModel import WhatsNewPagesModel
+
+from cura.Utils.NetworkingUtil import NetworkingUtil
from .SingleInstance import SingleInstance
from .AutoSave import AutoSave
from . import PlatformPhysics
from . import BuildVolume
from . import CameraAnimation
-from . import PrintInformation
from . import CuraActions
-from cura.Scene import ZOffsetDecorator
-from . import CuraSplashScreen
from . import PrintJobPreviewImageProvider
-from . import MachineActionManager
-
-from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager
-
-from cura.Settings.MachineManager import MachineManager
-from cura.Settings.ExtruderManager import ExtruderManager
-from cura.Settings.UserChangesModel import UserChangesModel
-from cura.Settings.ExtrudersModel import ExtrudersModel
-from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
-from cura.Settings.ContainerManager import ContainerManager
-from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel
-import cura.Settings.cura_empty_instance_containers
-from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
-
-from cura.ObjectsModel import ObjectsModel
-
-from cura.PrinterOutputDevice import PrinterOutputDevice
-from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
from cura import ApplicationMetadata, UltimakerCloudAuthentication
-
-from UM.FlameProfiler import pyqtSlot
-from UM.Decorators import override
+from cura.Settings.GlobalStack import GlobalStack
if TYPE_CHECKING:
- from cura.Machines.MaterialManager import MaterialManager
- from cura.Machines.QualityManager import QualityManager
from UM.Settings.EmptyInstanceContainer import EmptyInstanceContainer
- from cura.Settings.GlobalStack import GlobalStack
-
numpy.seterr(all = "ignore")
@@ -134,7 +145,7 @@ class CuraApplication(QtApplication):
# SettingVersion represents the set of settings available in the machine/extruder definitions.
# You need to make sure that this version number needs to be increased if there is any non-backwards-compatible
# changes of the settings.
- SettingVersion = 7
+ SettingVersion = 11
Created = False
@@ -150,6 +161,7 @@ class CuraApplication(QtApplication):
ExtruderStack = Resources.UserType + 9
DefinitionChangesContainer = Resources.UserType + 10
SettingVisibilityPreset = Resources.UserType + 11
+ IntentInstanceContainer = Resources.UserType + 12
Q_ENUMS(ResourceTypes)
@@ -186,13 +198,12 @@ class CuraApplication(QtApplication):
self.empty_container = None # type: EmptyInstanceContainer
self.empty_definition_changes_container = None # type: EmptyInstanceContainer
self.empty_variant_container = None # type: EmptyInstanceContainer
+ self.empty_intent_container = None # type: EmptyInstanceContainer
self.empty_material_container = None # type: EmptyInstanceContainer
self.empty_quality_container = None # type: EmptyInstanceContainer
self.empty_quality_changes_container = None # type: EmptyInstanceContainer
- self._variant_manager = None
self._material_manager = None
- self._quality_manager = None
self._machine_manager = None
self._extruder_manager = None
self._container_manager = None
@@ -208,6 +219,17 @@ class CuraApplication(QtApplication):
self._cura_scene_controller = None
self._machine_error_checker = None
+ self._machine_settings_manager = MachineSettingsManager(self, parent = self)
+ self._material_management_model = None
+ self._quality_management_model = None
+
+ self._discovered_printer_model = DiscoveredPrintersModel(self, parent = self)
+ self._first_start_machine_actions_model = None
+ self._welcome_pages_model = WelcomePagesModel(self, parent = self)
+ self._add_printer_pages_model = AddPrinterPagesModel(self, parent = self)
+ self._whats_new_pages_model = WhatsNewPagesModel(self, parent = self)
+ self._text_manager = TextManager(parent = self)
+
self._quality_profile_drop_down_menu_model = None
self._custom_quality_profile_drop_down_menu_model = None
self._cura_API = CuraAPI(self)
@@ -237,15 +259,12 @@ class CuraApplication(QtApplication):
self._update_platform_activity_timer = None
- self._need_to_show_user_agreement = True
-
self._sidebar_custom_menu_items = [] # type: list # Keeps list of custom menu items for the side bar
self._plugins_loaded = False
# Backups
- self._auto_save = None
- self._save_data_enabled = True
+ self._auto_save = None # type: Optional[AutoSave]
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
self._container_registry_class = CuraContainerRegistry
@@ -329,7 +348,7 @@ class CuraApplication(QtApplication):
# Adds expected directory names and search paths for Resources.
def __addExpectedResourceDirsAndSearchPaths(self):
# this list of dir names will be used by UM to detect an old cura directory
- for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "quality_changes", "user", "variants"]:
+ for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "quality_changes", "user", "variants", "intent"]:
Resources.addExpectedDirNameInData(dir_name)
Resources.addSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources"))
@@ -387,6 +406,7 @@ class CuraApplication(QtApplication):
Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances")
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
Resources.addStorageType(self.ResourceTypes.SettingVisibilityPreset, "setting_visibility")
+ Resources.addStorageType(self.ResourceTypes.IntentInstanceContainer, "intent")
self._container_registry.addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality")
self._container_registry.addResourceType(self.ResourceTypes.QualityChangesInstanceContainer, "quality_changes")
@@ -396,6 +416,7 @@ class CuraApplication(QtApplication):
self._container_registry.addResourceType(self.ResourceTypes.ExtruderStack, "extruder_train")
self._container_registry.addResourceType(self.ResourceTypes.MachineStack, "machine")
self._container_registry.addResourceType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
+ self._container_registry.addResourceType(self.ResourceTypes.IntentInstanceContainer, "intent")
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
Resources.addType(self.ResourceTypes.Firmware, "firmware")
@@ -405,7 +426,7 @@ class CuraApplication(QtApplication):
# Add empty variant, material and quality containers.
# Since they are empty, they should never be serialized and instead just programmatically created.
# We need them to simplify the switching between materials.
- self.empty_container = cura.Settings.cura_empty_instance_containers.empty_container # type: EmptyInstanceContainer
+ self.empty_container = cura.Settings.cura_empty_instance_containers.empty_container
self._container_registry.addContainer(
cura.Settings.cura_empty_instance_containers.empty_definition_changes_container)
@@ -414,6 +435,9 @@ class CuraApplication(QtApplication):
self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_variant_container)
self.empty_variant_container = cura.Settings.cura_empty_instance_containers.empty_variant_container
+ self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_intent_container)
+ self.empty_intent_container = cura.Settings.cura_empty_instance_containers.empty_intent_container
+
self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_material_container)
self.empty_material_container = cura.Settings.cura_empty_instance_containers.empty_material_container
@@ -428,14 +452,15 @@ class CuraApplication(QtApplication):
def __setLatestResouceVersionsForVersionUpgrade(self):
self._version_upgrade_manager.setCurrentVersions(
{
- ("quality", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
- ("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityChangesInstanceContainer, "application/x-uranium-instancecontainer"),
- ("machine_stack", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
- ("extruder_train", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
- ("preferences", Preferences.Version * 1000000 + self.SettingVersion): (Resources.Preferences, "application/x-uranium-preferences"),
- ("user", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer"),
- ("definition_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.DefinitionChangesContainer, "application/x-uranium-instancecontainer"),
- ("variant", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.VariantInstanceContainer, "application/x-uranium-instancecontainer"),
+ ("quality", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
+ ("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityChangesInstanceContainer, "application/x-uranium-instancecontainer"),
+ ("intent", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.IntentInstanceContainer, "application/x-uranium-instancecontainer"),
+ ("machine_stack", GlobalStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
+ ("extruder_train", ExtruderStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
+ ("preferences", Preferences.Version * 1000000 + self.SettingVersion): (Resources.Preferences, "application/x-uranium-preferences"),
+ ("user", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer"),
+ ("definition_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.DefinitionChangesContainer, "application/x-uranium-instancecontainer"),
+ ("variant", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.VariantInstanceContainer, "application/x-uranium-instancecontainer"),
}
)
@@ -450,7 +475,6 @@ class CuraApplication(QtApplication):
# Misc.:
"ConsoleLogger", #You want to be able to read the log if something goes wrong.
"CuraEngineBackend", #Cura is useless without this one since you can't slice.
- "UserAgreement", #Our lawyers want every user to see this at least once.
"FileLogger", #You want to be able to read the log if something goes wrong.
"XmlMaterialProfile", #Cura crashes without this one.
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
@@ -488,10 +512,13 @@ class CuraApplication(QtApplication):
self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading machines..."))
+ self._container_registry.allMetadataLoaded.connect(ContainerRegistry.getInstance)
+
with self._container_registry.lockFile():
self._container_registry.loadAllMetadata()
- # set the setting version for Preferences
+ self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up preferences..."))
+ # Set the setting version for Preferences
preferences = self.getPreferences()
preferences.addPreference("metadata/setting_version", 0)
preferences.setValue("metadata/setting_version", self.SettingVersion) #Don't make it equal to the default so that the setting version always gets written to the file.
@@ -509,8 +536,13 @@ class CuraApplication(QtApplication):
preferences.addPreference("cura/choice_on_profile_override", "always_ask")
preferences.addPreference("cura/choice_on_open_project", "always_ask")
preferences.addPreference("cura/use_multi_build_plate", False)
+ preferences.addPreference("cura/show_list_of_objects", False)
preferences.addPreference("view/settings_list_height", 400)
preferences.addPreference("view/settings_visible", False)
+ preferences.addPreference("view/settings_xpos", 0)
+ preferences.addPreference("view/settings_ypos", 56)
+ preferences.addPreference("view/colorscheme_xpos", 0)
+ preferences.addPreference("view/colorscheme_ypos", 56)
preferences.addPreference("cura/currency", "€")
preferences.addPreference("cura/material_settings", "{}")
@@ -522,7 +554,7 @@ class CuraApplication(QtApplication):
preferences.addPreference("cura/expanded_brands", "")
preferences.addPreference("cura/expanded_types", "")
- self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement")
+ preferences.addPreference("general/accepted_user_agreement", False)
for key in [
"dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin
@@ -545,13 +577,20 @@ class CuraApplication(QtApplication):
@pyqtProperty(bool)
def needToShowUserAgreement(self) -> bool:
- return self._need_to_show_user_agreement
+ return not UM.Util.parseBool(self.getPreferences().getValue("general/accepted_user_agreement"))
- def setNeedToShowUserAgreement(self, set_value = True) -> None:
- self._need_to_show_user_agreement = set_value
+ @pyqtSlot(bool)
+ def setNeedToShowUserAgreement(self, set_value: bool = True) -> None:
+ self.getPreferences().setValue("general/accepted_user_agreement", str(not set_value))
+
+ @pyqtSlot(str, str)
+ def writeToLog(self, severity: str, message: str) -> None:
+ Logger.log(severity, message)
# DO NOT call this function to close the application, use checkAndExitApplication() instead which will perform
# pre-exit checks such as checking for in-progress USB printing, etc.
+ # Except for the 'Decline and close' in the 'User Agreement'-step in the Welcome-pages, that should be a hard exit.
+ @pyqtSlot()
def closeApplication(self) -> None:
Logger.log("i", "Close application")
main_window = self.getMainWindow()
@@ -604,9 +643,17 @@ class CuraApplication(QtApplication):
## A reusable dialogbox
#
- showMessageBox = pyqtSignal(str, str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText", "buttons", "icon"])
+ showMessageBox = pyqtSignal(str,str, str, str, int, int,
+ arguments = ["title", "text", "informativeText", "detailedText","buttons", "icon"])
- def messageBox(self, title, text, informativeText = "", detailedText = "", buttons = QMessageBox.Ok, icon = QMessageBox.NoIcon, callback = None, callback_arguments = []):
+ def messageBox(self, title, text,
+ informativeText = "",
+ detailedText = "",
+ buttons = QMessageBox.Ok,
+ icon = QMessageBox.NoIcon,
+ callback = None,
+ callback_arguments = []
+ ):
self._message_box_callback = callback
self._message_box_callback_arguments = callback_arguments
self.showMessageBox.emit(title, text, informativeText, detailedText, buttons, icon)
@@ -632,14 +679,14 @@ class CuraApplication(QtApplication):
def discardOrKeepProfileChangesClosed(self, option: str) -> None:
global_stack = self.getGlobalContainerStack()
if option == "discard":
- for extruder in global_stack.extruders.values():
+ for extruder in global_stack.extruderList:
extruder.userChanges.clear()
global_stack.userChanges.clear()
# if the user decided to keep settings then the user settings should be re-calculated and validated for errors
# before slicing. To ensure that slicer uses right settings values
elif option == "keep":
- for extruder in global_stack.extruders.values():
+ for extruder in global_stack.extruderList:
extruder.userChanges.update()
global_stack.userChanges.update()
@@ -649,13 +696,10 @@ class CuraApplication(QtApplication):
self._message_box_callback(button, *self._message_box_callback_arguments)
self._message_box_callback = None
self._message_box_callback_arguments = []
-
- def setSaveDataEnabled(self, enabled: bool) -> None:
- self._save_data_enabled = enabled
# Cura has multiple locations where instance containers need to be saved, so we need to handle this differently.
def saveSettings(self):
- if not self.started or not self._save_data_enabled:
+ if not self.started:
# Do not do saving during application start or when data should not be saved on quit.
return
ContainerRegistry.getInstance().saveDirtyContainers()
@@ -676,6 +720,8 @@ class CuraApplication(QtApplication):
## Handle loading of all plugin types (and the backend explicitly)
# \sa PluginRegistry
def _loadPlugins(self) -> None:
+ self._plugin_registry.setCheckIfTrusted(ApplicationMetadata.IsEnterpriseVersion)
+
self._plugin_registry.addType("profile_reader", self._addProfileReader)
self._plugin_registry.addType("profile_writer", self._addProfileWriter)
@@ -699,21 +745,6 @@ class CuraApplication(QtApplication):
def run(self):
super().run()
- container_registry = self._container_registry
-
- Logger.log("i", "Initializing variant manager")
- self._variant_manager = VariantManager(container_registry)
- self._variant_manager.initialize()
-
- Logger.log("i", "Initializing material manager")
- from cura.Machines.MaterialManager import MaterialManager
- self._material_manager = MaterialManager(container_registry, parent = self)
- self._material_manager.initialize()
-
- Logger.log("i", "Initializing quality manager")
- from cura.Machines.QualityManager import QualityManager
- self._quality_manager = QualityManager(self, parent = self)
- self._quality_manager.initialize()
Logger.log("i", "Initializing machine manager")
self._machine_manager = MachineManager(self, parent = self)
@@ -745,6 +776,11 @@ class CuraApplication(QtApplication):
# Initialize Cura API
self._cura_API.initialize()
+ self._output_device_manager.start()
+ self._welcome_pages_model.initialize()
+ self._add_printer_pages_model.initialize()
+ self._whats_new_pages_model.initialize()
+
# Detect in which mode to run and execute that mode
if self._is_headless:
self.runWithoutGUI()
@@ -810,7 +846,6 @@ class CuraApplication(QtApplication):
if diagonal < 1: #No printer added yet. Set a default camera distance for normal-sized printers.
diagonal = 375
camera.setPosition(Vector(-80, 250, 700) * diagonal / 375)
- camera.setPerspective(True)
camera.lookAt(Vector(0, 0, 0))
controller.getScene().setActiveCamera("3d")
@@ -839,10 +874,42 @@ class CuraApplication(QtApplication):
# Hide the splash screen
self.closeSplash()
+ @pyqtSlot(result = QObject)
+ def getDiscoveredPrintersModel(self, *args) -> "DiscoveredPrintersModel":
+ return self._discovered_printer_model
+
+ @pyqtSlot(result = QObject)
+ def getFirstStartMachineActionsModel(self, *args) -> "FirstStartMachineActionsModel":
+ if self._first_start_machine_actions_model is None:
+ self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self)
+ if self.started:
+ self._first_start_machine_actions_model.initialize()
+ return self._first_start_machine_actions_model
+
@pyqtSlot(result = QObject)
def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel:
return self._setting_visibility_presets_model
+ @pyqtSlot(result = QObject)
+ def getWelcomePagesModel(self, *args) -> "WelcomePagesModel":
+ return self._welcome_pages_model
+
+ @pyqtSlot(result = QObject)
+ def getAddPrinterPagesModel(self, *args) -> "AddPrinterPagesModel":
+ return self._add_printer_pages_model
+
+ @pyqtSlot(result = QObject)
+ def getWhatsNewPagesModel(self, *args) -> "WhatsNewPagesModel":
+ return self._whats_new_pages_model
+
+ @pyqtSlot(result = QObject)
+ def getMachineSettingsManager(self, *args) -> "MachineSettingsManager":
+ return self._machine_settings_manager
+
+ @pyqtSlot(result = QObject)
+ def getTextManager(self, *args) -> "TextManager":
+ return self._text_manager
+
def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions":
if self._cura_formula_functions is None:
self._cura_formula_functions = CuraFormulaFunctions(self)
@@ -861,20 +928,12 @@ class CuraApplication(QtApplication):
self._extruder_manager = ExtruderManager()
return self._extruder_manager
- def getVariantManager(self, *args) -> VariantManager:
- return self._variant_manager
-
- @pyqtSlot(result = QObject)
- def getMaterialManager(self, *args) -> "MaterialManager":
- return self._material_manager
-
- @pyqtSlot(result = QObject)
- def getQualityManager(self, *args) -> "QualityManager":
- return self._quality_manager
+ def getIntentManager(self, *args) -> IntentManager:
+ return IntentManager.getInstance()
def getObjectsModel(self, *args):
if self._object_manager is None:
- self._object_manager = ObjectsModel.createObjectsModel()
+ self._object_manager = ObjectsModel(self)
return self._object_manager
@pyqtSlot(result = QObject)
@@ -918,6 +977,18 @@ class CuraApplication(QtApplication):
def getMachineActionManager(self, *args):
return self._machine_action_manager
+ @pyqtSlot(result = QObject)
+ def getMaterialManagementModel(self) -> MaterialManagementModel:
+ if not self._material_management_model:
+ self._material_management_model = MaterialManagementModel(parent = self)
+ return self._material_management_model
+
+ @pyqtSlot(result = QObject)
+ def getQualityManagementModel(self) -> QualityManagementModel:
+ if not self._quality_management_model:
+ self._quality_management_model = QualityManagementModel(parent = self)
+ return self._quality_management_model
+
def getSimpleModeSettingsManager(self, *args):
if self._simple_mode_settings_manager is None:
self._simple_mode_settings_manager = SimpleModeSettingsManager()
@@ -933,7 +1004,7 @@ class CuraApplication(QtApplication):
return super().event(event)
- def getAutoSave(self):
+ def getAutoSave(self) -> Optional[AutoSave]:
return self._auto_save
## Get print information (duration / material used)
@@ -971,13 +1042,22 @@ class CuraApplication(QtApplication):
qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 0, "SceneController", self.getCuraSceneController)
qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager)
qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager)
+ qmlRegisterSingletonType(IntentManager, "Cura", 1, 6, "IntentManager", self.getIntentManager)
qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", self.getSettingInheritanceManager)
qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager)
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
+ qmlRegisterType(NetworkingUtil, "Cura", 1, 5, "NetworkingUtil")
+
+ qmlRegisterType(WelcomePagesModel, "Cura", 1, 0, "WelcomePagesModel")
+ qmlRegisterType(WhatsNewPagesModel, "Cura", 1, 0, "WhatsNewPagesModel")
+ qmlRegisterType(AddPrinterPagesModel, "Cura", 1, 0, "AddPrinterPagesModel")
+ qmlRegisterType(TextManager, "Cura", 1, 0, "TextManager")
+ qmlRegisterType(RecommendedMode, "Cura", 1, 0, "RecommendedMode")
+
qmlRegisterType(NetworkMJPGImage, "Cura", 1, 0, "NetworkMJPGImage")
- qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel)
+ qmlRegisterType(ObjectsModel, "Cura", 1, 0, "ObjectsModel")
qmlRegisterType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel")
qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel")
qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer")
@@ -987,18 +1067,23 @@ class CuraApplication(QtApplication):
qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel")
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel")
- qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
- qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")
+ qmlRegisterSingletonType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel", self.getQualityManagementModel)
+ qmlRegisterSingletonType(MaterialManagementModel, "Cura", 1, 5, "MaterialManagementModel", self.getMaterialManagementModel)
+
+ qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel")
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
"QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0,
"CustomQualityProfilesDropDownMenuModel", self.getCustomQualityProfilesDropDownMenuModel)
qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel")
+ qmlRegisterType(IntentModel, "Cura", 1, 6, "IntentModel")
+ qmlRegisterType(IntentCategoryModel, "Cura", 1, 6, "IntentCategoryModel")
qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")
qmlRegisterType(SettingVisibilityPresetsModel, "Cura", 1, 0, "SettingVisibilityPresetsModel")
qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel")
+ qmlRegisterType(FirstStartMachineActionsModel, "Cura", 1, 0, "FirstStartMachineActionsModel")
qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel")
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.getInstance)
@@ -1055,7 +1140,6 @@ class CuraApplication(QtApplication):
self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
self._camera_animation.start()
- requestAddPrinter = pyqtSignal()
activityChanged = pyqtSignal()
sceneBoundingBoxChanged = pyqtSignal()
@@ -1197,7 +1281,7 @@ class CuraApplication(QtApplication):
@pyqtSlot()
def arrangeObjectsToAllBuildPlates(self) -> None:
nodes_to_arrange = []
- for node in DepthFirstIterator(self.getController().getScene().getRoot()): # type: ignore
+ for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not isinstance(node, SceneNode):
continue
@@ -1224,7 +1308,7 @@ class CuraApplication(QtApplication):
def arrangeAll(self) -> None:
nodes_to_arrange = []
active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
- for node in DepthFirstIterator(self.getController().getScene().getRoot()): # type: ignore
+ for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not isinstance(node, SceneNode):
continue
@@ -1262,7 +1346,13 @@ class CuraApplication(QtApplication):
Logger.log("i", "Reloading all loaded mesh data.")
nodes = []
has_merged_nodes = False
- for node in DepthFirstIterator(self.getController().getScene().getRoot()): # type: ignore
+ gcode_filename = None # type: Optional[str]
+ for node in DepthFirstIterator(self.getController().getScene().getRoot()):
+ # Objects loaded from Gcode should also be included.
+ gcode_filename = node.callDecoration("getGcodeFileName")
+ if gcode_filename is not None:
+ break
+
if not isinstance(node, CuraSceneNode) or not node.getMeshData():
if node.getName() == "MergedMesh":
has_merged_nodes = True
@@ -1270,21 +1360,29 @@ class CuraApplication(QtApplication):
nodes.append(node)
+ # We can open only one gcode file at the same time. If the current view has a gcode file open, just reopen it
+ # for reloading.
+ if gcode_filename:
+ self._openFile(gcode_filename)
+
if not nodes:
return
for node in nodes:
- file_name = node.getMeshData().getFileName()
- if file_name:
- job = ReadMeshJob(file_name)
- job._node = node # type: ignore
- job.finished.connect(self._reloadMeshFinished)
- if has_merged_nodes:
- job.finished.connect(self.updateOriginOfMergedMeshes)
+ mesh_data = node.getMeshData()
- job.start()
- else:
- Logger.log("w", "Unable to reload data because we don't have a filename.")
+ if mesh_data:
+ file_name = mesh_data.getFileName()
+ if file_name:
+ job = ReadMeshJob(file_name)
+ job._node = node # type: ignore
+ job.finished.connect(self._reloadMeshFinished)
+ if has_merged_nodes:
+ job.finished.connect(self.updateOriginOfMergedMeshes)
+
+ job.start()
+ else:
+ Logger.log("w", "Unable to reload data because we don't have a filename.")
@pyqtSlot("QStringList")
def setExpandedCategories(self, categories: List[str]) -> None:
@@ -1515,8 +1613,12 @@ class CuraApplication(QtApplication):
openProjectFile = pyqtSignal(QUrl, arguments = ["project_file"]) # Emitted when a project file is about to open.
- @pyqtSlot(QUrl, bool)
- def readLocalFile(self, file, skip_project_file_check = False):
+ @pyqtSlot(QUrl, str)
+ @pyqtSlot(QUrl)
+ ## Open a local file
+ # \param project_mode How to handle project files. Either None(default): Follow user preference, "open_as_model" or
+ # "open_as_project". This parameter is only considered if the file is a project file.
+ def readLocalFile(self, file: QUrl, project_mode: Optional[str] = None):
if not file.isValid():
return
@@ -1527,10 +1629,24 @@ class CuraApplication(QtApplication):
self.deleteAll()
break
- if not skip_project_file_check and self.checkIsValidProjectFile(file):
+ is_project_file = self.checkIsValidProjectFile(file)
+
+ if project_mode is None:
+ project_mode = self.getPreferences().getValue("cura/choice_on_open_project")
+
+ if is_project_file and project_mode == "open_as_project":
+ # open as project immediately without presenting a dialog
+ workspace_handler = self.getWorkspaceFileHandler()
+ workspace_handler.readLocalFile(file)
+ return
+
+ if is_project_file and project_mode == "always_ask":
+ # present a dialog asking to open as project or import models
self.callLater(self.openProjectFile.emit, file)
return
+ # Either the file is a model file or we want to load only models from project. Continue to load models.
+
if self.getPreferences().getValue("cura/select_models_on_load"):
Selection.clear()
@@ -1591,7 +1707,7 @@ class CuraApplication(QtApplication):
arranger = Arrange.create(x = machine_width, y = machine_depth, fixed_nodes = fixed_nodes)
min_offset = 8
default_extruder_position = self.getMachineManager().defaultExtruderPosition
- default_extruder_id = self._global_container_stack.extruders[default_extruder_position].getId()
+ default_extruder_id = self._global_container_stack.extruderList[int(default_extruder_position)].getId()
select_models_on_load = self.getPreferences().getValue("cura/select_models_on_load")
@@ -1685,7 +1801,7 @@ class CuraApplication(QtApplication):
try:
result = workspace_reader.preRead(file_path, show_dialog=False)
return result == WorkspaceReader.PreReadResult.accepted
- except Exception as e:
+ except Exception:
Logger.logException("e", "Could not check file %s", file_url)
return False
@@ -1715,3 +1831,73 @@ class CuraApplication(QtApplication):
def getSidebarCustomMenuItems(self) -> list:
return self._sidebar_custom_menu_items
+ @pyqtSlot(result = bool)
+ def shouldShowWelcomeDialog(self) -> bool:
+ # Only show the complete flow if there is no printer yet.
+ return self._machine_manager.activeMachine is None
+
+ @pyqtSlot(result = bool)
+ def shouldShowWhatsNewDialog(self) -> bool:
+ has_active_machine = self._machine_manager.activeMachine is not None
+ has_app_just_upgraded = self.hasJustUpdatedFromOldVersion()
+
+ # Only show the what's new dialog if there's no machine and we have just upgraded
+ show_whatsnew_only = has_active_machine and has_app_just_upgraded
+ return show_whatsnew_only
+
+ @pyqtSlot(result = int)
+ def appWidth(self) -> int:
+ main_window = QtApplication.getInstance().getMainWindow()
+ if main_window:
+ return main_window.width()
+ else:
+ return 0
+
+ @pyqtSlot(result = int)
+ def appHeight(self) -> int:
+ main_window = QtApplication.getInstance().getMainWindow()
+ if main_window:
+ return main_window.height()
+ else:
+ return 0
+
+ @pyqtSlot()
+ def deleteAll(self, only_selectable: bool = True) -> None:
+ super().deleteAll(only_selectable = only_selectable)
+
+ # Also remove nodes with LayerData
+ self._removeNodesWithLayerData(only_selectable = only_selectable)
+
+ def _removeNodesWithLayerData(self, only_selectable: bool = True) -> None:
+ Logger.log("i", "Clearing scene")
+ nodes = []
+ for node in DepthFirstIterator(self.getController().getScene().getRoot()):
+ if not isinstance(node, SceneNode):
+ continue
+ if not node.isEnabled():
+ continue
+ if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
+ continue # Node that doesnt have a mesh and is not a group.
+ if only_selectable and not node.isSelectable():
+ continue # Only remove nodes that are selectable.
+ if not node.callDecoration("isSliceable") and not node.callDecoration("getLayerData") and not node.callDecoration("isGroup"):
+ continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
+ nodes.append(node)
+ if nodes:
+ from UM.Operations.GroupedOperation import GroupedOperation
+ op = GroupedOperation()
+
+ for node in nodes:
+ from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
+ op.addOperation(RemoveSceneNodeOperation(node))
+
+ # Reset the print information
+ self.getController().getScene().sceneChanged.emit(node)
+
+ op.push()
+ from UM.Scene.Selection import Selection
+ Selection.clear()
+
+ @classmethod
+ def getInstance(cls, *args, **kwargs) -> "CuraApplication":
+ return cast(CuraApplication, super().getInstance(**kwargs))
diff --git a/cura/CuraVersion.py.in b/cura/CuraVersion.py.in
index 1a500df248..4583e76f67 100644
--- a/cura/CuraVersion.py.in
+++ b/cura/CuraVersion.py.in
@@ -6,7 +6,6 @@ CuraAppDisplayName = "@CURA_APP_DISPLAY_NAME@"
CuraVersion = "@CURA_VERSION@"
CuraBuildType = "@CURA_BUILDTYPE@"
CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False
-CuraSDKVersion = "@CURA_SDK_VERSION@"
CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@"
CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@"
CuraCloudAccountAPIRoot = "@CURA_CLOUD_ACCOUNT_API_ROOT@"
diff --git a/cura/CuraView.py b/cura/CuraView.py
index 978c651b43..b358558dff 100644
--- a/cura/CuraView.py
+++ b/cura/CuraView.py
@@ -3,8 +3,11 @@
from PyQt5.QtCore import pyqtProperty, QUrl
+from UM.Resources import Resources
from UM.View.View import View
+from cura.CuraApplication import CuraApplication
+
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
# to indicate this.
@@ -12,13 +15,20 @@ from UM.View.View import View
# the stageMenuComponent returns an item that should be used somehwere in the stage menu. It's up to the active stage
# to actually do something with this.
class CuraView(View):
- def __init__(self, parent = None) -> None:
+ def __init__(self, parent = None, use_empty_menu_placeholder: bool = False) -> None:
super().__init__(parent)
+ self._empty_menu_placeholder_url = QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
+ "EmptyViewMenuComponent.qml"))
+ self._use_empty_menu_placeholder = use_empty_menu_placeholder
+
@pyqtProperty(QUrl, constant = True)
def mainComponent(self) -> QUrl:
return self.getDisplayComponent("main")
@pyqtProperty(QUrl, constant = True)
def stageMenuComponent(self) -> QUrl:
- return self.getDisplayComponent("menu")
\ No newline at end of file
+ url = self.getDisplayComponent("menu")
+ if not url.toString() and self._use_empty_menu_placeholder:
+ url = self._empty_menu_placeholder_url
+ return url
diff --git a/cura/Layer.py b/cura/Layer.py
index 9cd45380fc..73fda64a45 100644
--- a/cura/Layer.py
+++ b/cura/Layer.py
@@ -1,14 +1,20 @@
-from UM.Mesh.MeshBuilder import MeshBuilder
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import List
import numpy
+from UM.Mesh.MeshBuilder import MeshBuilder
+from UM.Mesh.MeshData import MeshData
+from cura.LayerPolygon import LayerPolygon
+
class Layer:
- def __init__(self, layer_id):
+ def __init__(self, layer_id: int) -> None:
self._id = layer_id
self._height = 0.0
self._thickness = 0.0
- self._polygons = []
+ self._polygons = [] # type: List[LayerPolygon]
self._element_count = 0
@property
@@ -20,7 +26,7 @@ class Layer:
return self._thickness
@property
- def polygons(self):
+ def polygons(self) -> List[LayerPolygon]:
return self._polygons
@property
@@ -33,14 +39,14 @@ class Layer:
def setThickness(self, thickness):
self._thickness = thickness
- def lineMeshVertexCount(self):
+ def lineMeshVertexCount(self) -> int:
result = 0
for polygon in self._polygons:
result += polygon.lineMeshVertexCount()
return result
- def lineMeshElementCount(self):
+ def lineMeshElementCount(self) -> int:
result = 0
for polygon in self._polygons:
result += polygon.lineMeshElementCount()
@@ -57,18 +63,18 @@ class Layer:
result_index_offset += polygon.lineMeshElementCount()
self._element_count += polygon.elementCount
- return (result_vertex_offset, result_index_offset)
+ return result_vertex_offset, result_index_offset
- def createMesh(self):
+ def createMesh(self) -> MeshData:
return self.createMeshOrJumps(True)
- def createJumps(self):
+ def createJumps(self) -> MeshData:
return self.createMeshOrJumps(False)
# Defines the two triplets of local point indices to use to draw the two faces for each line segment in createMeshOrJump
__index_pattern = numpy.array([[0, 3, 2, 0, 1, 3]], dtype = numpy.int32 )
- def createMeshOrJumps(self, make_mesh):
+ def createMeshOrJumps(self, make_mesh: bool) -> MeshData:
builder = MeshBuilder()
line_count = 0
@@ -79,14 +85,14 @@ class Layer:
for polygon in self._polygons:
line_count += polygon.jumpCount
- # Reserve the neccesary space for the data upfront
+ # Reserve the necessary space for the data upfront
builder.reserveFaceAndVertexCount(2 * line_count, 4 * line_count)
for polygon in self._polygons:
- # Filter out the types of lines we are not interesed in depending on whether we are drawing the mesh or the jumps.
+ # Filter out the types of lines we are not interested in depending on whether we are drawing the mesh or the jumps.
index_mask = numpy.logical_not(polygon.jumpMask) if make_mesh else polygon.jumpMask
- # Create an array with rows [p p+1] and only keep those we whant to draw based on make_mesh
+ # Create an array with rows [p p+1] and only keep those we want to draw based on make_mesh
points = numpy.concatenate((polygon.data[:-1], polygon.data[1:]), 1)[index_mask.ravel()]
# Line types of the points we want to draw
line_types = polygon.types[index_mask]
diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py
index 072d5f94f5..0d6489aaa2 100644
--- a/cura/LayerPolygon.py
+++ b/cura/LayerPolygon.py
@@ -1,7 +1,7 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from UM.Application import Application
+from UM.Qt.QtApplication import QtApplication
from typing import Any, Optional
import numpy
@@ -20,7 +20,7 @@ class LayerPolygon:
MoveCombingType = 8
MoveRetractionType = 9
SupportInterfaceType = 10
- PrimeTower = 11
+ PrimeTowerType = 11
__number_of_types = 12
__jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType, numpy.arange(__number_of_types) == MoveCombingType), numpy.arange(__number_of_types) == MoveRetractionType)
@@ -61,19 +61,19 @@ class LayerPolygon:
# When type is used as index returns true if type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType
# Should be generated in better way, not hardcoded.
- self._isInfillOrSkinTypeMap = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1], dtype=numpy.bool)
+ self._isInfillOrSkinTypeMap = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0], dtype = numpy.bool)
self._build_cache_line_mesh_mask = None # type: Optional[numpy.ndarray]
self._build_cache_needed_points = None # type: Optional[numpy.ndarray]
def buildCache(self) -> None:
# For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out.
- self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype=bool)
+ self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype = bool)
mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask)
self._index_begin = 0
self._index_end = mesh_line_count
- self._build_cache_needed_points = numpy.ones((len(self._types), 2), dtype=numpy.bool)
+ self._build_cache_needed_points = numpy.ones((len(self._types), 2), dtype = numpy.bool)
# Only if the type of line segment changes do we need to add an extra vertex to change colors
self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1]
# Mark points as unneeded if they are of types we don't want in the line mesh according to the calculated mask
@@ -136,9 +136,9 @@ class LayerPolygon:
self._index_begin += index_offset
self._index_end += index_offset
- indices[self._index_begin:self._index_end, :] = numpy.arange(self._index_end-self._index_begin, dtype=numpy.int32).reshape((-1, 1))
+ indices[self._index_begin:self._index_end, :] = numpy.arange(self._index_end-self._index_begin, dtype = numpy.int32).reshape((-1, 1))
# When the line type changes the index needs to be increased by 2.
- indices[self._index_begin:self._index_end, :] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(), 0], dtype=numpy.int32).reshape((-1, 1))
+ indices[self._index_begin:self._index_end, :] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(), 0], dtype = numpy.int32).reshape((-1, 1))
# Each line segment goes from it's starting point p to p+1, offset by the vertex index.
# The -1 is to compensate for the neccecarily True value of needed_points_list[0,0] which causes an unwanted +1 in cumsum above.
indices[self._index_begin:self._index_end, :] += numpy.array([self._vertex_begin - 1, self._vertex_begin])
@@ -232,7 +232,7 @@ class LayerPolygon:
@classmethod
def getColorMap(cls):
if cls.__color_map is None:
- theme = Application.getInstance().getTheme()
+ theme = QtApplication.getInstance().getTheme()
cls.__color_map = numpy.array([
theme.getColor("layerview_none").getRgbF(), # NoneType
theme.getColor("layerview_inset_0").getRgbF(), # Inset0Type
@@ -245,7 +245,7 @@ class LayerPolygon:
theme.getColor("layerview_move_combing").getRgbF(), # MoveCombingType
theme.getColor("layerview_move_retraction").getRgbF(), # MoveRetractionType
theme.getColor("layerview_support_interface").getRgbF(), # SupportInterfaceType
- theme.getColor("layerview_prime_tower").getRgbF()
+ theme.getColor("layerview_prime_tower").getRgbF() # PrimeTowerType
])
return cls.__color_map
diff --git a/cura/MachineAction.py b/cura/MachineAction.py
index 94b096f9c1..0f05401c89 100644
--- a/cura/MachineAction.py
+++ b/cura/MachineAction.py
@@ -2,8 +2,9 @@
# Cura is released under the terms of the LGPLv3 or higher.
import os
+from typing import Optional
-from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
+from PyQt5.QtCore import QObject, QUrl, pyqtSlot, pyqtProperty, pyqtSignal
from UM.Logger import Logger
from UM.PluginObject import PluginObject
@@ -33,6 +34,12 @@ class MachineAction(QObject, PluginObject):
def getKey(self) -> str:
return self._key
+ ## Whether this action needs to ask the user anything.
+ # If not, we shouldn't present the user with certain screens which otherwise show up.
+ # Defaults to true to be in line with the old behaviour.
+ def needsUserInteraction(self) -> bool:
+ return True
+
@pyqtProperty(str, notify = labelChanged)
def label(self) -> str:
return self._label
@@ -66,18 +73,26 @@ class MachineAction(QObject, PluginObject):
return self._finished
## Protected helper to create a view object based on provided QML.
- def _createViewFromQML(self) -> None:
+ def _createViewFromQML(self) -> Optional["QObject"]:
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
if plugin_path is None:
Logger.log("e", "Cannot create QML view: cannot find plugin path for plugin [%s]", self.getPluginId())
- return
+ return None
path = os.path.join(plugin_path, self._qml_url)
from cura.CuraApplication import CuraApplication
- self._view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
+ view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
+ return view
- @pyqtProperty(QObject, constant = True)
- def displayItem(self):
- if not self._view:
- self._createViewFromQML()
- return self._view
+ @pyqtProperty(QUrl, constant = True)
+ def qmlPath(self) -> "QUrl":
+ plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
+ if plugin_path is None:
+ Logger.log("e", "Cannot create QML view: cannot find plugin path for plugin [%s]", self.getPluginId())
+ return QUrl("")
+ path = os.path.join(plugin_path, self._qml_url)
+ return QUrl.fromLocalFile(path)
+
+ @pyqtSlot(result = QObject)
+ def getDisplayItem(self) -> Optional["QObject"]:
+ return self._createViewFromQML()
diff --git a/cura/Machines/ContainerNode.py b/cura/Machines/ContainerNode.py
index eef1c63127..a8bbf0a537 100644
--- a/cura/Machines/ContainerNode.py
+++ b/cura/Machines/ContainerNode.py
@@ -1,64 +1,64 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional, Any, Dict, Union, TYPE_CHECKING
-
-from collections import OrderedDict
+from typing import Any, Dict, Optional
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
+from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Logger import Logger
from UM.Settings.InstanceContainer import InstanceContainer
-##
-# A metadata / container combination. Use getContainer() to get the container corresponding to the metadata.
-#
-# ContainerNode is a multi-purpose class. It has two main purposes:
-# 1. It encapsulates an InstanceContainer. It contains that InstanceContainer's
-# - metadata (Always)
-# - container (lazy-loaded when needed)
-# 2. It also serves as a node in a hierarchical InstanceContainer lookup table/tree.
-# This is used in Variant, Material, and Quality Managers.
+## A node in the container tree. It represents one container.
#
+# The container it represents is referenced by its container_id. During normal
+# use of the tree, this container is not constructed. Only when parts of the
+# tree need to get loaded in the container stack should it get constructed.
class ContainerNode:
- __slots__ = ("_metadata", "_container", "children_map")
+ ## Creates a new node for the container tree.
+ # \param container_id The ID of the container that this node should
+ # represent.
+ def __init__(self, container_id: str) -> None:
+ self.container_id = container_id
+ self._container = None # type: Optional[InstanceContainer]
+ self.children_map = {} # type: Dict[str, ContainerNode] # Mapping from container ID to container node.
- def __init__(self, metadata: Optional[Dict[str, Any]] = None) -> None:
- self._metadata = metadata
- self._container = None # type: Optional[InstanceContainer]
- self.children_map = OrderedDict() # type: ignore # This is because it's children are supposed to override it.
+ ## Gets the metadata of the container that this node represents.
+ # Getting the metadata from the container directly is about 10x as fast.
+ # \return The metadata of the container in this node.
+ def getMetadata(self):
+ return ContainerRegistry.getInstance().findContainersMetadata(id = self.container_id)[0]
- ## Get an entry value from the metadata
+ ## Get an entry from the metadata of the container that this node contains.
+ #
+ # This is just a convenience function.
+ # \param entry The metadata entry key to return.
+ # \param default If the metadata is not present or the container is not
+ # found, the value of this default is returned.
+ # \return The value of the metadata entry, or the default if it was not
+ # present.
def getMetaDataEntry(self, entry: str, default: Any = None) -> Any:
- if self._metadata is None:
+ container_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = self.container_id)
+ if len(container_metadata) == 0:
return default
- return self._metadata.get(entry, default)
+ return container_metadata[0].get(entry, default)
- def getMetadata(self) -> Dict[str, Any]:
- if self._metadata is None:
- return {}
- return self._metadata
-
- def getChildNode(self, child_key: str) -> Optional["ContainerNode"]:
- return self.children_map.get(child_key)
-
- def getContainer(self) -> Optional["InstanceContainer"]:
- if self._metadata is None:
- Logger.log("e", "Cannot get container for a ContainerNode without metadata.")
- return None
-
- if self._container is None:
- container_id = self._metadata["id"]
- from UM.Settings.ContainerRegistry import ContainerRegistry
- container_list = ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
- if not container_list:
- Logger.log("e", "Failed to lazy-load container [{container_id}]. Cannot find it.".format(container_id = container_id))
+ ## The container that this node's container ID refers to.
+ #
+ # This can be used to finally instantiate the container in order to put it
+ # in the container stack.
+ # \return A container.
+ @property
+ def container(self) -> Optional[InstanceContainer]:
+ if not self._container:
+ container_list = ContainerRegistry.getInstance().findInstanceContainers(id = self.container_id)
+ if len(container_list) == 0:
+ Logger.log("e", "Failed to lazy-load container [{container_id}]. Cannot find it.".format(container_id = self.container_id))
error_message = ConfigurationErrorMessage.getInstance()
- error_message.addFaultyContainers(container_id)
+ error_message.addFaultyContainers(self.container_id)
return None
self._container = container_list[0]
-
return self._container
def __str__(self) -> str:
- return "%s[%s]" % (self.__class__.__name__, self.getMetaDataEntry("id"))
+ return "%s[%s]" % (self.__class__.__name__, self.container_id)
\ No newline at end of file
diff --git a/cura/Machines/ContainerTree.py b/cura/Machines/ContainerTree.py
new file mode 100644
index 0000000000..c2bfabea2c
--- /dev/null
+++ b/cura/Machines/ContainerTree.py
@@ -0,0 +1,158 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from UM.Job import Job # For our background task of loading MachineNodes lazily.
+from UM.JobQueue import JobQueue # For our background task of loading MachineNodes lazily.
+from UM.Logger import Logger
+from UM.Settings.ContainerRegistry import ContainerRegistry # To listen to containers being added.
+from UM.Signal import Signal
+import cura.CuraApplication # Imported like this to prevent circular dependencies.
+from cura.Machines.MachineNode import MachineNode
+from cura.Settings.GlobalStack import GlobalStack # To listen only to global stacks being added.
+
+from typing import Dict, List, Optional, TYPE_CHECKING
+import time
+
+if TYPE_CHECKING:
+ from cura.Machines.QualityGroup import QualityGroup
+ from cura.Machines.QualityChangesGroup import QualityChangesGroup
+ from UM.Settings.ContainerStack import ContainerStack
+
+
+## This class contains a look-up tree for which containers are available at
+# which stages of configuration.
+#
+# The tree starts at the machine definitions. For every distinct definition
+# there will be one machine node here.
+#
+# All of the fallbacks for material choices, quality choices, etc. should be
+# encoded in this tree. There must always be at least one child node (for
+# nodes that have children) but that child node may be a node representing the
+# empty instance container.
+class ContainerTree:
+ __instance = None
+
+ @classmethod
+ def getInstance(cls):
+ if cls.__instance is None:
+ cls.__instance = ContainerTree()
+ return cls.__instance
+
+ def __init__(self) -> None:
+ self.machines = self._MachineNodeMap() # Mapping from definition ID to machine nodes with lazy loading.
+ self.materialsChanged = Signal() # Emitted when any of the material nodes in the tree got changed.
+ cura.CuraApplication.CuraApplication.getInstance().initializationFinished.connect(self._onStartupFinished) # Start the background task to load more machine nodes after start-up is completed.
+
+ ## Get the quality groups available for the currently activated printer.
+ #
+ # This contains all quality groups, enabled or disabled. To check whether
+ # the quality group can be activated, test for the
+ # ``QualityGroup.is_available`` property.
+ # \return For every quality type, one quality group.
+ def getCurrentQualityGroups(self) -> Dict[str, "QualityGroup"]:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return {}
+ variant_names = [extruder.variant.getName() for extruder in global_stack.extruderList]
+ material_bases = [extruder.material.getMetaDataEntry("base_file") for extruder in global_stack.extruderList]
+ extruder_enabled = [extruder.isEnabled for extruder in global_stack.extruderList]
+ return self.machines[global_stack.definition.getId()].getQualityGroups(variant_names, material_bases, extruder_enabled)
+
+ ## Get the quality changes groups available for the currently activated
+ # printer.
+ #
+ # This contains all quality changes groups, enabled or disabled. To check
+ # whether the quality changes group can be activated, test for the
+ # ``QualityChangesGroup.is_available`` property.
+ # \return A list of all quality changes groups.
+ def getCurrentQualityChangesGroups(self) -> List["QualityChangesGroup"]:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return []
+ variant_names = [extruder.variant.getName() for extruder in global_stack.extruderList]
+ material_bases = [extruder.material.getMetaDataEntry("base_file") for extruder in global_stack.extruderList]
+ extruder_enabled = [extruder.isEnabled for extruder in global_stack.extruderList]
+ return self.machines[global_stack.definition.getId()].getQualityChangesGroups(variant_names, material_bases, extruder_enabled)
+
+ ## Ran after completely starting up the application.
+ def _onStartupFinished(self):
+ currently_added = ContainerRegistry.getInstance().findContainerStacks() # Find all currently added global stacks.
+ JobQueue.getInstance().add(self._MachineNodeLoadJob(self, currently_added))
+
+ ## Dictionary-like object that contains the machines.
+ #
+ # This handles the lazy loading of MachineNodes.
+ class _MachineNodeMap:
+ def __init__(self) -> None:
+ self._machines = {} # type: Dict[str, MachineNode]
+
+ ## Returns whether a printer with a certain definition ID exists. This
+ # is regardless of whether or not the printer is loaded yet.
+ # \param definition_id The definition to look for.
+ # \return Whether or not a printer definition exists with that name.
+ def __contains__(self, definition_id: str) -> bool:
+ return len(ContainerRegistry.getInstance().findContainersMetadata(id = definition_id)) > 0
+
+ ## Returns a machine node for the specified definition ID.
+ #
+ # If the machine node wasn't loaded yet, this will load it lazily.
+ # \param definition_id The definition to look for.
+ # \return A machine node for that definition.
+ def __getitem__(self, definition_id: str) -> MachineNode:
+ if definition_id not in self._machines:
+ start_time = time.time()
+ self._machines[definition_id] = MachineNode(definition_id)
+ self._machines[definition_id].materialsChanged.connect(ContainerTree.getInstance().materialsChanged)
+ Logger.log("d", "Adding container tree for {definition_id} took {duration} seconds.".format(definition_id = definition_id, duration = time.time() - start_time))
+ return self._machines[definition_id]
+
+ ## Gets a machine node for the specified definition ID, with default.
+ #
+ # The default is returned if there is no definition with the specified
+ # ID. If the machine node wasn't loaded yet, this will load it lazily.
+ # \param definition_id The definition to look for.
+ # \param default The machine node to return if there is no machine
+ # with that definition (can be ``None`` optionally or if not
+ # provided).
+ # \return A machine node for that definition, or the default if there
+ # is no definition with the provided definition_id.
+ def get(self, definition_id: str, default: Optional[MachineNode] = None) -> Optional[MachineNode]:
+ if definition_id not in self:
+ return default
+ return self[definition_id]
+
+ ## Returns whether we've already cached this definition's node.
+ # \param definition_id The definition that we may have cached.
+ # \return ``True`` if it's cached.
+ def is_loaded(self, definition_id: str) -> bool:
+ return definition_id in self._machines
+
+ ## Pre-loads all currently added printers as a background task so that
+ # switching printers in the interface is faster.
+ class _MachineNodeLoadJob(Job):
+ ## Creates a new background task.
+ # \param tree_root The container tree instance. This cannot be
+ # obtained through the singleton static function since the instance
+ # may not yet be constructed completely.
+ # \param container_stacks All of the stacks to pre-load the container
+ # trees for. This needs to be provided from here because the stacks
+ # need to be constructed on the main thread because they are QObject.
+ def __init__(self, tree_root: "ContainerTree", container_stacks: List["ContainerStack"]):
+ self.tree_root = tree_root
+ self.container_stacks = container_stacks
+ super().__init__()
+
+ ## Starts the background task.
+ #
+ # The ``JobQueue`` will schedule this on a different thread.
+ def run(self) -> None:
+ for stack in self.container_stacks: # Load all currently-added containers.
+ if not isinstance(stack, GlobalStack):
+ continue
+ # Allow a thread switch after every container.
+ # Experimentally, sleep(0) didn't allow switching. sleep(0.1) or sleep(0.2) neither.
+ # We're in no hurry though. Half a second is fine.
+ time.sleep(0.5)
+ definition_id = stack.definition.getId()
+ if not self.tree_root.machines.is_loaded(definition_id):
+ _ = self.tree_root.machines[definition_id]
diff --git a/cura/Machines/IntentNode.py b/cura/Machines/IntentNode.py
new file mode 100644
index 0000000000..2b3a596f81
--- /dev/null
+++ b/cura/Machines/IntentNode.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import TYPE_CHECKING
+
+from UM.Settings.ContainerRegistry import ContainerRegistry
+
+from cura.Machines.ContainerNode import ContainerNode
+
+if TYPE_CHECKING:
+ from cura.Machines.QualityNode import QualityNode
+
+
+## This class represents an intent profile in the container tree.
+#
+# This class has no more subnodes.
+class IntentNode(ContainerNode):
+ def __init__(self, container_id: str, quality: "QualityNode") -> None:
+ super().__init__(container_id)
+ self.quality = quality
+ self.intent_category = ContainerRegistry.getInstance().findContainersMetadata(id = container_id)[0].get("intent_category", "default")
diff --git a/cura/Machines/MachineErrorChecker.py b/cura/Machines/MachineErrorChecker.py
index fb11123af6..4c6ed891b1 100644
--- a/cura/Machines/MachineErrorChecker.py
+++ b/cura/Machines/MachineErrorChecker.py
@@ -58,7 +58,6 @@ class MachineErrorChecker(QObject):
# Whenever the machine settings get changed, we schedule an error check.
self._machine_manager.globalContainerChanged.connect(self.startErrorCheck)
- self._machine_manager.globalValueChanged.connect(self.startErrorCheck)
self._onMachineChanged()
@@ -67,7 +66,7 @@ class MachineErrorChecker(QObject):
self._global_stack.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.disconnect(self.startErrorCheck)
- for extruder in self._global_stack.extruders.values():
+ for extruder in self._global_stack.extruderList:
extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.disconnect(self.startErrorCheck)
@@ -77,7 +76,7 @@ class MachineErrorChecker(QObject):
self._global_stack.propertyChanged.connect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.connect(self.startErrorCheck)
- for extruder in self._global_stack.extruders.values():
+ for extruder in self._global_stack.extruderList:
extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.connect(self.startErrorCheck)
@@ -127,7 +126,7 @@ class MachineErrorChecker(QObject):
# Populate the (stack, key) tuples to check
self._stacks_and_keys_to_check = deque()
- for stack in [global_stack] + list(global_stack.extruders.values()):
+ for stack in global_stack.extruderList:
for key in stack.getAllKeys():
self._stacks_and_keys_to_check.append((stack, key))
@@ -168,7 +167,7 @@ class MachineErrorChecker(QObject):
if validator_type:
validator = validator_type(key)
validation_state = validator(stack)
- if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
+ if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError, ValidatorState.Invalid):
# Finish
self._setResult(True)
return
diff --git a/cura/Machines/MachineNode.py b/cura/Machines/MachineNode.py
new file mode 100644
index 0000000000..92f71b409b
--- /dev/null
+++ b/cura/Machines/MachineNode.py
@@ -0,0 +1,183 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Dict, List
+
+from UM.Logger import Logger
+from UM.Signal import Signal
+from UM.Util import parseBool
+from UM.Settings.ContainerRegistry import ContainerRegistry # To find all the variants for this machine.
+
+import cura.CuraApplication # Imported like this to prevent circular dependencies.
+from cura.Machines.ContainerNode import ContainerNode
+from cura.Machines.QualityChangesGroup import QualityChangesGroup # To construct groups of quality changes profiles that belong together.
+from cura.Machines.QualityGroup import QualityGroup # To construct groups of quality profiles that belong together.
+from cura.Machines.QualityNode import QualityNode
+from cura.Machines.VariantNode import VariantNode
+import UM.FlameProfiler
+
+
+## This class represents a machine in the container tree.
+#
+# The subnodes of these nodes are variants.
+class MachineNode(ContainerNode):
+ def __init__(self, container_id: str) -> None:
+ super().__init__(container_id)
+ self.variants = {} # type: Dict[str, VariantNode] # Mapping variant names to their nodes.
+ self.global_qualities = {} # type: Dict[str, QualityNode] # Mapping quality types to the global quality for those types.
+ self.materialsChanged = Signal() # Emitted when one of the materials underneath this machine has been changed.
+
+ container_registry = ContainerRegistry.getInstance()
+ try:
+ my_metadata = container_registry.findContainersMetadata(id = container_id)[0]
+ except IndexError:
+ Logger.log("Unable to find metadata for container %s", container_id)
+ my_metadata = {}
+ # Some of the metadata is cached upon construction here.
+ # ONLY DO THAT FOR METADATA THAT DOESN'T CHANGE DURING RUNTIME!
+ # Otherwise you need to keep it up-to-date during runtime.
+ self.has_materials = parseBool(my_metadata.get("has_materials", "true"))
+ self.has_variants = parseBool(my_metadata.get("has_variants", "false"))
+ self.has_machine_quality = parseBool(my_metadata.get("has_machine_quality", "false"))
+ self.quality_definition = my_metadata.get("quality_definition", container_id) if self.has_machine_quality else "fdmprinter"
+ self.exclude_materials = my_metadata.get("exclude_materials", [])
+ self.preferred_variant_name = my_metadata.get("preferred_variant_name", "")
+ self.preferred_material = my_metadata.get("preferred_material", "")
+ self.preferred_quality_type = my_metadata.get("preferred_quality_type", "")
+
+ self._loadAll()
+
+ ## Get the available quality groups for this machine.
+ #
+ # This returns all quality groups, regardless of whether they are
+ # available to the combination of extruders or not. On the resulting
+ # quality groups, the is_available property is set to indicate whether the
+ # quality group can be selected according to the combination of extruders
+ # in the parameters.
+ # \param variant_names The names of the variants loaded in each extruder.
+ # \param material_bases The base file names of the materials loaded in
+ # each extruder.
+ # \param extruder_enabled Whether or not the extruders are enabled. This
+ # allows the function to set the is_available properly.
+ # \return For each available quality type, a QualityGroup instance.
+ def getQualityGroups(self, variant_names: List[str], material_bases: List[str], extruder_enabled: List[bool]) -> Dict[str, QualityGroup]:
+ if len(variant_names) != len(material_bases) or len(variant_names) != len(extruder_enabled):
+ Logger.log("e", "The number of extruders in the list of variants (" + str(len(variant_names)) + ") is not equal to the number of extruders in the list of materials (" + str(len(material_bases)) + ") or the list of enabled extruders (" + str(len(extruder_enabled)) + ").")
+ return {}
+ # For each extruder, find which quality profiles are available. Later we'll intersect the quality types.
+ qualities_per_type_per_extruder = [{}] * len(variant_names) # type: List[Dict[str, QualityNode]]
+ for extruder_nr, variant_name in enumerate(variant_names):
+ if not extruder_enabled[extruder_nr]:
+ continue # No qualities are available in this extruder. It'll get skipped when calculating the available quality types.
+ material_base = material_bases[extruder_nr]
+ if variant_name not in self.variants or material_base not in self.variants[variant_name].materials:
+ # The printer has no variant/material-specific quality profiles. Use the global quality profiles.
+ qualities_per_type_per_extruder[extruder_nr] = self.global_qualities
+ else:
+ # Use the actually specialised quality profiles.
+ qualities_per_type_per_extruder[extruder_nr] = {node.quality_type: node for node in self.variants[variant_name].materials[material_base].qualities.values()}
+
+ # Create the quality group for each available type.
+ quality_groups = {}
+ for quality_type, global_quality_node in self.global_qualities.items():
+ if not global_quality_node.container:
+ Logger.log("w", "Node {0} doesn't have a container.".format(global_quality_node.container_id))
+ continue
+ quality_groups[quality_type] = QualityGroup(name = global_quality_node.getMetaDataEntry("name", "Unnamed profile"), quality_type = quality_type)
+ quality_groups[quality_type].node_for_global = global_quality_node
+ for extruder_position, qualities_per_type in enumerate(qualities_per_type_per_extruder):
+ if quality_type in qualities_per_type:
+ quality_groups[quality_type].setExtruderNode(extruder_position, qualities_per_type[quality_type])
+
+ available_quality_types = set(quality_groups.keys())
+ for extruder_nr, qualities_per_type in enumerate(qualities_per_type_per_extruder):
+ if not extruder_enabled[extruder_nr]:
+ continue
+ available_quality_types.intersection_update(qualities_per_type.keys())
+ for quality_type in available_quality_types:
+ quality_groups[quality_type].is_available = True
+ return quality_groups
+
+ ## Returns all of the quality changes groups available to this printer.
+ #
+ # The quality changes groups store which quality type and intent category
+ # they were made for, but not which material and nozzle. Instead for the
+ # quality type and intent category, the quality changes will always be
+ # available but change the quality type and intent category when
+ # activated.
+ #
+ # The quality changes group does depend on the printer: Which quality
+ # definition is used.
+ #
+ # The quality changes groups that are available do depend on the quality
+ # types that are available, so it must still be known which extruders are
+ # enabled and which materials and variants are loaded in them. This allows
+ # setting the correct is_available flag.
+ # \param variant_names The names of the variants loaded in each extruder.
+ # \param material_bases The base file names of the materials loaded in
+ # each extruder.
+ # \param extruder_enabled For each extruder whether or not they are
+ # enabled.
+ # \return List of all quality changes groups for the printer.
+ def getQualityChangesGroups(self, variant_names: List[str], material_bases: List[str], extruder_enabled: List[bool]) -> List[QualityChangesGroup]:
+ machine_quality_changes = ContainerRegistry.getInstance().findContainersMetadata(type = "quality_changes", definition = self.quality_definition) # All quality changes for each extruder.
+
+ groups_by_name = {} #type: Dict[str, QualityChangesGroup] # Group quality changes profiles by their display name. The display name must be unique for quality changes. This finds profiles that belong together in a group.
+ for quality_changes in machine_quality_changes:
+ name = quality_changes["name"]
+ if name not in groups_by_name:
+ # CURA-6599
+ # For some reason, QML will get null or fail to convert type for MachineManager.activeQualityChangesGroup() to
+ # a QObject. Setting the object ownership to QQmlEngine.CppOwnership doesn't work, but setting the object
+ # parent to application seems to work.
+ from cura.CuraApplication import CuraApplication
+ groups_by_name[name] = QualityChangesGroup(name, quality_type = quality_changes["quality_type"],
+ intent_category = quality_changes.get("intent_category", "default"),
+ parent = CuraApplication.getInstance())
+ # CURA-6882
+ # Custom qualities are always available, even if they are based on the "not supported" profile.
+ groups_by_name[name].is_available = True
+ elif groups_by_name[name].intent_category == "default": # Intent category should be stored as "default" if everything is default or as the intent if any of the extruder have an actual intent.
+ groups_by_name[name].intent_category = quality_changes.get("intent_category", "default")
+
+ if quality_changes.get("position") is not None and quality_changes.get("position") != "None": # An extruder profile.
+ groups_by_name[name].metadata_per_extruder[int(quality_changes["position"])] = quality_changes
+ else: # Global profile.
+ groups_by_name[name].metadata_for_global = quality_changes
+
+ return list(groups_by_name.values())
+
+ ## Gets the preferred global quality node, going by the preferred quality
+ # type.
+ #
+ # If the preferred global quality is not in there, an arbitrary global
+ # quality is taken.
+ # If there are no global qualities, an empty quality is returned.
+ def preferredGlobalQuality(self) -> "QualityNode":
+ return self.global_qualities.get(self.preferred_quality_type, next(iter(self.global_qualities.values())))
+
+ ## (Re)loads all variants under this printer.
+ @UM.FlameProfiler.profile
+ def _loadAll(self) -> None:
+ container_registry = ContainerRegistry.getInstance()
+ if not self.has_variants:
+ self.variants["empty"] = VariantNode("empty_variant", machine = self)
+ else:
+ # Find all the variants for this definition ID.
+ variants = container_registry.findInstanceContainersMetadata(type = "variant", definition = self.container_id, hardware_type = "nozzle")
+ for variant in variants:
+ variant_name = variant["name"]
+ if variant_name not in self.variants:
+ self.variants[variant_name] = VariantNode(variant["id"], machine = self)
+ self.variants[variant_name].materialsChanged.connect(self.materialsChanged)
+ if not self.variants:
+ self.variants["empty"] = VariantNode("empty_variant", machine = self)
+
+ # Find the global qualities for this printer.
+ global_qualities = container_registry.findInstanceContainersMetadata(type = "quality", definition = self.quality_definition, global_quality = "True") # First try specific to this printer.
+ if len(global_qualities) == 0: # This printer doesn't override the global qualities.
+ global_qualities = container_registry.findInstanceContainersMetadata(type = "quality", definition = "fdmprinter", global_quality = "True") # Otherwise pick the global global qualities.
+ if len(global_qualities) == 0: # There are no global qualities either?! Something went very wrong, but we'll not crash and properly fill the tree.
+ global_qualities = [cura.CuraApplication.CuraApplication.getInstance().empty_quality_container.getMetaData()]
+ for global_quality in global_qualities:
+ self.global_qualities[global_quality["quality_type"]] = QualityNode(global_quality["id"], parent = self)
diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py
deleted file mode 100644
index aff79218c8..0000000000
--- a/cura/Machines/MaterialManager.py
+++ /dev/null
@@ -1,708 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from collections import defaultdict, OrderedDict
-import copy
-import uuid
-from typing import Dict, Optional, TYPE_CHECKING, Any, Set, List, cast, Tuple
-
-from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot
-
-from UM.Application import Application
-from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
-from UM.Logger import Logger
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.SettingFunction import SettingFunction
-from UM.Util import parseBool
-
-from .MaterialNode import MaterialNode
-from .MaterialGroup import MaterialGroup
-from .VariantType import VariantType
-
-if TYPE_CHECKING:
- from UM.Settings.DefinitionContainer import DefinitionContainer
- from UM.Settings.InstanceContainer import InstanceContainer
- from cura.Settings.GlobalStack import GlobalStack
- from cura.Settings.ExtruderStack import ExtruderStack
-
-
-#
-# MaterialManager maintains a number of maps and trees for material lookup.
-# The models GUI and QML use are now only dependent on the MaterialManager. That means as long as the data in
-# MaterialManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI.
-#
-# For now, updating the lookup maps and trees here is very simple: we discard the old data completely and recreate them
-# again. This means the update is exactly the same as initialization. There are performance concerns about this approach
-# but so far the creation of the tables and maps is very fast and there is no noticeable slowness, we keep it like this
-# because it's simple.
-#
-class MaterialManager(QObject):
-
- materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated.
- favoritesUpdated = pyqtSignal() # Emitted whenever the favorites are changed
-
- def __init__(self, container_registry, parent = None):
- super().__init__(parent)
- self._application = Application.getInstance()
- self._container_registry = container_registry # type: ContainerRegistry
-
- # Material_type -> generic material metadata
- self._fallback_materials_map = dict() # type: Dict[str, Dict[str, Any]]
-
- # Root_material_id -> MaterialGroup
- self._material_group_map = dict() # type: Dict[str, MaterialGroup]
-
- # Approximate diameter str
- self._diameter_machine_nozzle_buildplate_material_map = dict() # type: Dict[str, Dict[str, MaterialNode]]
-
- # We're using these two maps to convert between the specific diameter material id and the generic material id
- # because the generic material ids are used in qualities and definitions, while the specific diameter material is meant
- # i.e. generic_pla -> generic_pla_175
- # root_material_id -> approximate diameter str -> root_material_id for that diameter
- self._material_diameter_map = defaultdict(dict) # type: Dict[str, Dict[str, str]]
-
- # Material id including diameter (generic_pla_175) -> material root id (generic_pla)
- self._diameter_material_map = dict() # type: Dict[str, str]
-
- # This is used in Legacy UM3 send material function and the material management page.
- # GUID -> a list of material_groups
- self._guid_material_groups_map = defaultdict(list) # type: Dict[str, List[MaterialGroup]]
-
- # The machine definition ID for the non-machine-specific materials.
- # This is used as the last fallback option if the given machine-specific material(s) cannot be found.
- self._default_machine_definition_id = "fdmprinter"
- self._default_approximate_diameter_for_quality_search = "3"
-
- # When a material gets added/imported, there can be more than one InstanceContainers. In those cases, we don't
- # want to react on every container/metadata changed signal. The timer here is to buffer it a bit so we don't
- # react too many time.
- self._update_timer = QTimer(self)
- self._update_timer.setInterval(300)
- self._update_timer.setSingleShot(True)
- self._update_timer.timeout.connect(self._updateMaps)
-
- self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged)
- self._container_registry.containerAdded.connect(self._onContainerMetadataChanged)
- self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged)
-
- self._favorites = set() # type: Set[str]
-
- def initialize(self) -> None:
- # Find all materials and put them in a matrix for quick search.
- material_metadatas = {metadata["id"]: metadata for metadata in
- self._container_registry.findContainersMetadata(type = "material") if
- metadata.get("GUID")} # type: Dict[str, Dict[str, Any]]
-
- self._material_group_map = dict() # type: Dict[str, MaterialGroup]
-
- # Map #1
- # root_material_id -> MaterialGroup
- for material_id, material_metadata in material_metadatas.items():
- # We don't store empty material in the lookup tables
- if material_id == "empty_material":
- continue
-
- root_material_id = material_metadata.get("base_file", "")
- if root_material_id not in self._material_group_map:
- self._material_group_map[root_material_id] = MaterialGroup(root_material_id, MaterialNode(material_metadatas[root_material_id]))
- self._material_group_map[root_material_id].is_read_only = self._container_registry.isReadOnly(root_material_id)
- group = self._material_group_map[root_material_id]
-
- # Store this material in the group of the appropriate root material.
- if material_id != root_material_id:
- new_node = MaterialNode(material_metadata)
- group.derived_material_node_list.append(new_node)
-
- # Order this map alphabetically so it's easier to navigate in a debugger
- self._material_group_map = OrderedDict(sorted(self._material_group_map.items(), key = lambda x: x[0]))
-
- # Map #1.5
- # GUID -> material group list
- self._guid_material_groups_map = defaultdict(list) # type: Dict[str, List[MaterialGroup]]
- for root_material_id, material_group in self._material_group_map.items():
- guid = material_group.root_material_node.getMetaDataEntry("GUID", "")
- self._guid_material_groups_map[guid].append(material_group)
-
- # Map #2
- # Lookup table for material type -> fallback material metadata, only for read-only materials
- grouped_by_type_dict = dict() # type: Dict[str, Any]
- material_types_without_fallback = set()
- for root_material_id, material_node in self._material_group_map.items():
- material_type = material_node.root_material_node.getMetaDataEntry("material", "")
- if material_type not in grouped_by_type_dict:
- grouped_by_type_dict[material_type] = {"generic": None,
- "others": []}
- material_types_without_fallback.add(material_type)
- brand = material_node.root_material_node.getMetaDataEntry("brand", "")
- if brand.lower() == "generic":
- to_add = True
- if material_type in grouped_by_type_dict:
- diameter = material_node.root_material_node.getMetaDataEntry("approximate_diameter", "")
- if diameter != self._default_approximate_diameter_for_quality_search:
- to_add = False # don't add if it's not the default diameter
-
- if to_add:
- # Checking this first allow us to differentiate between not read only materials:
- # - if it's in the list, it means that is a new material without fallback
- # - if it is not, then it is a custom material with a fallback material (parent)
- if material_type in material_types_without_fallback:
- grouped_by_type_dict[material_type] = material_node.root_material_node._metadata
- material_types_without_fallback.remove(material_type)
-
- # Remove the materials that have no fallback materials
- for material_type in material_types_without_fallback:
- del grouped_by_type_dict[material_type]
- self._fallback_materials_map = grouped_by_type_dict
-
- # Map #3
- # There can be multiple material profiles for the same material with different diameters, such as "generic_pla"
- # and "generic_pla_175". This is inconvenient when we do material-specific quality lookup because a quality can
- # be for either "generic_pla" or "generic_pla_175", but not both. This map helps to get the correct material ID
- # for quality search.
- self._material_diameter_map = defaultdict(dict)
- self._diameter_material_map = dict()
-
- # Group the material IDs by the same name, material, brand, and color but with different diameters.
- material_group_dict = dict() # type: Dict[Tuple[Any], Dict[str, str]]
- keys_to_fetch = ("name", "material", "brand", "color")
- for root_material_id, machine_node in self._material_group_map.items():
- root_material_metadata = machine_node.root_material_node._metadata
-
- key_data_list = [] # type: List[Any]
- for key in keys_to_fetch:
- key_data_list.append(machine_node.root_material_node.getMetaDataEntry(key))
- key_data = cast(Tuple[Any], tuple(key_data_list)) # type: Tuple[Any]
-
- # If the key_data doesn't exist, it doesn't matter if the material is read only...
- if key_data not in material_group_dict:
- material_group_dict[key_data] = dict()
- else:
- # ...but if key_data exists, we just overwrite it if the material is read only, otherwise we skip it
- if not machine_node.is_read_only:
- continue
- approximate_diameter = machine_node.root_material_node.getMetaDataEntry("approximate_diameter", "")
- material_group_dict[key_data][approximate_diameter] = machine_node.root_material_node.getMetaDataEntry("id", "")
-
- # Map [root_material_id][diameter] -> root_material_id for this diameter
- for data_dict in material_group_dict.values():
- for root_material_id1 in data_dict.values():
- if root_material_id1 in self._material_diameter_map:
- continue
- diameter_map = data_dict
- for root_material_id2 in data_dict.values():
- self._material_diameter_map[root_material_id2] = diameter_map
-
- default_root_material_id = data_dict.get(self._default_approximate_diameter_for_quality_search)
- if default_root_material_id is None:
- default_root_material_id = list(data_dict.values())[0] # no default diameter present, just take "the" only one
- for root_material_id in data_dict.values():
- self._diameter_material_map[root_material_id] = default_root_material_id
-
- # Map #4
- # "machine" -> "nozzle name" -> "buildplate name" -> "root material ID" -> specific material InstanceContainer
- self._diameter_machine_nozzle_buildplate_material_map = dict() # type: Dict[str, Dict[str, MaterialNode]]
- for material_metadata in material_metadatas.values():
- self.__addMaterialMetadataIntoLookupTree(material_metadata)
-
- favorites = self._application.getPreferences().getValue("cura/favorite_materials")
- for item in favorites.split(";"):
- self._favorites.add(item)
-
- self.materialsUpdated.emit()
-
- def __addMaterialMetadataIntoLookupTree(self, material_metadata: Dict[str, Any]) -> None:
- material_id = material_metadata["id"]
-
- # We don't store empty material in the lookup tables
- if material_id == "empty_material":
- return
-
- root_material_id = material_metadata["base_file"]
- definition = material_metadata["definition"]
- approximate_diameter = material_metadata["approximate_diameter"]
-
- if approximate_diameter not in self._diameter_machine_nozzle_buildplate_material_map:
- self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] = {}
-
- machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[
- approximate_diameter]
- if definition not in machine_nozzle_buildplate_material_map:
- machine_nozzle_buildplate_material_map[definition] = MaterialNode()
-
- # This is a list of information regarding the intermediate nodes:
- # nozzle -> buildplate
- nozzle_name = material_metadata.get("variant_name")
- buildplate_name = material_metadata.get("buildplate_name")
- intermediate_node_info_list = [(nozzle_name, VariantType.NOZZLE),
- (buildplate_name, VariantType.BUILD_PLATE),
- ]
-
- variant_manager = self._application.getVariantManager()
-
- machine_node = machine_nozzle_buildplate_material_map[definition]
- current_node = machine_node
- current_intermediate_node_info_idx = 0
- error_message = None # type: Optional[str]
- while current_intermediate_node_info_idx < len(intermediate_node_info_list):
- variant_name, variant_type = intermediate_node_info_list[current_intermediate_node_info_idx]
- if variant_name is not None:
- # The new material has a specific variant, so it needs to be added to that specific branch in the tree.
- variant = variant_manager.getVariantNode(definition, variant_name, variant_type)
- if variant is None:
- error_message = "Material {id} contains a variant {name} that does not exist.".format(
- id = material_metadata["id"], name = variant_name)
- break
-
- # Update the current node to advance to a more specific branch
- if variant_name not in current_node.children_map:
- current_node.children_map[variant_name] = MaterialNode()
- current_node = current_node.children_map[variant_name]
-
- current_intermediate_node_info_idx += 1
-
- if error_message is not None:
- Logger.log("e", "%s It will not be added into the material lookup tree.", error_message)
- self._container_registry.addWrongContainerId(material_metadata["id"])
- return
-
- # Add the material to the current tree node, which is the deepest (the most specific) branch we can find.
- # Sanity check: Make sure that there is no duplicated materials.
- if root_material_id in current_node.material_map:
- Logger.log("e", "Duplicated material [%s] with root ID [%s]. It has already been added.",
- material_id, root_material_id)
- ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id)
- return
-
- current_node.material_map[root_material_id] = MaterialNode(material_metadata)
-
- def _updateMaps(self):
- Logger.log("i", "Updating material lookup data ...")
- self.initialize()
-
- def _onContainerMetadataChanged(self, container):
- self._onContainerChanged(container)
-
- def _onContainerChanged(self, container):
- container_type = container.getMetaDataEntry("type")
- if container_type != "material":
- return
-
- # update the maps
- self._update_timer.start()
-
- def getMaterialGroup(self, root_material_id: str) -> Optional[MaterialGroup]:
- return self._material_group_map.get(root_material_id)
-
- def getRootMaterialIDForDiameter(self, root_material_id: str, approximate_diameter: str) -> str:
- return self._material_diameter_map.get(root_material_id, {}).get(approximate_diameter, root_material_id)
-
- def getRootMaterialIDWithoutDiameter(self, root_material_id: str) -> str:
- return self._diameter_material_map.get(root_material_id, "")
-
- def getMaterialGroupListByGUID(self, guid: str) -> Optional[List[MaterialGroup]]:
- return self._guid_material_groups_map.get(guid)
-
- # Returns a dict of all material groups organized by root_material_id.
- def getAllMaterialGroups(self) -> Dict[str, "MaterialGroup"]:
- return self._material_group_map
-
- #
- # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup.
- #
- def getAvailableMaterials(self, machine_definition: "DefinitionContainer", nozzle_name: Optional[str],
- buildplate_name: Optional[str], diameter: float) -> Dict[str, MaterialNode]:
- # round the diameter to get the approximate diameter
- rounded_diameter = str(round(diameter))
- if rounded_diameter not in self._diameter_machine_nozzle_buildplate_material_map:
- Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s])", diameter, rounded_diameter)
- return dict()
-
- machine_definition_id = machine_definition.getId()
-
- # If there are nozzle-and-or-buildplate materials, get the nozzle-and-or-buildplate material
- machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[rounded_diameter]
- machine_node = machine_nozzle_buildplate_material_map.get(machine_definition_id)
- default_machine_node = machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id)
- nozzle_node = None
- buildplate_node = None
- if nozzle_name is not None and machine_node is not None:
- nozzle_node = machine_node.getChildNode(nozzle_name)
- # Get buildplate node if possible
- if nozzle_node is not None and buildplate_name is not None:
- buildplate_node = nozzle_node.getChildNode(buildplate_name)
-
- nodes_to_check = [buildplate_node, nozzle_node, machine_node, default_machine_node]
-
- # Fallback mechanism of finding materials:
- # 1. buildplate-specific material
- # 2. nozzle-specific material
- # 3. machine-specific material
- # 4. generic material (for fdmprinter)
- machine_exclude_materials = machine_definition.getMetaDataEntry("exclude_materials", [])
-
- material_id_metadata_dict = dict() # type: Dict[str, MaterialNode]
- excluded_materials = set()
- for current_node in nodes_to_check:
- if current_node is None:
- continue
-
- # Only exclude the materials that are explicitly specified in the "exclude_materials" field.
- # Do not exclude other materials that are of the same type.
- for material_id, node in current_node.material_map.items():
- if material_id in machine_exclude_materials:
- excluded_materials.add(material_id)
- continue
-
- if material_id not in material_id_metadata_dict:
- material_id_metadata_dict[material_id] = node
-
- if excluded_materials:
- Logger.log("d", "Exclude materials {excluded_materials} for machine {machine_definition_id}".format(excluded_materials = ", ".join(excluded_materials), machine_definition_id = machine_definition_id))
-
- return material_id_metadata_dict
-
- #
- # A convenience function to get available materials for the given machine with the extruder position.
- #
- def getAvailableMaterialsForMachineExtruder(self, machine: "GlobalStack",
- extruder_stack: "ExtruderStack") -> Optional[Dict[str, MaterialNode]]:
- buildplate_name = machine.getBuildplateName()
- nozzle_name = None
- if extruder_stack.variant.getId() != "empty_variant":
- nozzle_name = extruder_stack.variant.getName()
- diameter = extruder_stack.getApproximateMaterialDiameter()
-
- # Fetch the available materials (ContainerNode) for the current active machine and extruder setup.
- return self.getAvailableMaterials(machine.definition, nozzle_name, buildplate_name, diameter)
-
- #
- # Gets MaterialNode for the given extruder and machine with the given material name.
- # Returns None if:
- # 1. the given machine doesn't have materials;
- # 2. cannot find any material InstanceContainers with the given settings.
- #
- def getMaterialNode(self, machine_definition_id: str, nozzle_name: Optional[str],
- buildplate_name: Optional[str], diameter: float, root_material_id: str) -> Optional["MaterialNode"]:
- # round the diameter to get the approximate diameter
- rounded_diameter = str(round(diameter))
- if rounded_diameter not in self._diameter_machine_nozzle_buildplate_material_map:
- Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s]) for root material id [%s]",
- diameter, rounded_diameter, root_material_id)
- return None
-
- # If there are nozzle materials, get the nozzle-specific material
- machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[rounded_diameter] # type: Dict[str, MaterialNode]
- machine_node = machine_nozzle_buildplate_material_map.get(machine_definition_id)
- nozzle_node = None
- buildplate_node = None
-
- # Fallback for "fdmprinter" if the machine-specific materials cannot be found
- if machine_node is None:
- machine_node = machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id)
- if machine_node is not None and nozzle_name is not None:
- nozzle_node = machine_node.getChildNode(nozzle_name)
- if nozzle_node is not None and buildplate_name is not None:
- buildplate_node = nozzle_node.getChildNode(buildplate_name)
-
- # Fallback mechanism of finding materials:
- # 1. buildplate-specific material
- # 2. nozzle-specific material
- # 3. machine-specific material
- # 4. generic material (for fdmprinter)
- nodes_to_check = [buildplate_node, nozzle_node, machine_node,
- machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id)]
-
- material_node = None
- for node in nodes_to_check:
- if node is not None:
- material_node = node.material_map.get(root_material_id)
- if material_node:
- break
-
- return material_node
-
- #
- # Gets MaterialNode for the given extruder and machine with the given material type.
- # Returns None if:
- # 1. the given machine doesn't have materials;
- # 2. cannot find any material InstanceContainers with the given settings.
- #
- def getMaterialNodeByType(self, global_stack: "GlobalStack", position: str, nozzle_name: str,
- buildplate_name: Optional[str], material_guid: str) -> Optional["MaterialNode"]:
- node = None
- machine_definition = global_stack.definition
- extruder_definition = global_stack.extruders[position].definition
- if parseBool(machine_definition.getMetaDataEntry("has_materials", False)):
- material_diameter = extruder_definition.getProperty("material_diameter", "value")
- if isinstance(material_diameter, SettingFunction):
- material_diameter = material_diameter(global_stack)
-
- # Look at the guid to material dictionary
- root_material_id = None
- for material_group in self._guid_material_groups_map[material_guid]:
- root_material_id = cast(str, material_group.root_material_node.getMetaDataEntry("id", ""))
- break
-
- if not root_material_id:
- Logger.log("i", "Cannot find materials with guid [%s] ", material_guid)
- return None
-
- node = self.getMaterialNode(machine_definition.getId(), nozzle_name, buildplate_name,
- material_diameter, root_material_id)
- return node
-
- # There are 2 ways to get fallback materials;
- # - A fallback by type (@sa getFallbackMaterialIdByMaterialType), which adds the generic version of this material
- # - A fallback by GUID; If a material has been duplicated, it should also check if the original materials do have
- # a GUID. This should only be done if the material itself does not have a quality just yet.
- def getFallBackMaterialIdsByMaterial(self, material: "InstanceContainer") -> List[str]:
- results = [] # type: List[str]
-
- material_groups = self.getMaterialGroupListByGUID(material.getMetaDataEntry("GUID"))
- for material_group in material_groups: # type: ignore
- if material_group.name != material.getId():
- # If the material in the group is read only, put it at the front of the list (since that is the most
- # likely one to get a result)
- if material_group.is_read_only:
- results.insert(0, material_group.name)
- else:
- results.append(material_group.name)
-
- fallback = self.getFallbackMaterialIdByMaterialType(material.getMetaDataEntry("material"))
- if fallback is not None:
- results.append(fallback)
- return results
-
- #
- # Used by QualityManager. Built-in quality profiles may be based on generic material IDs such as "generic_pla".
- # For materials such as ultimaker_pla_orange, no quality profiles may be found, so we should fall back to use
- # the generic material IDs to search for qualities.
- #
- # An example would be, suppose we have machine with preferred material set to "filo3d_pla" (1.75mm), but its
- # extruders only use 2.85mm materials, then we won't be able to find the preferred material for this machine.
- # A fallback would be to fetch a generic material of the same type "PLA" as "filo3d_pla", and in this case it will
- # be "generic_pla". This function is intended to get a generic fallback material for the given material type.
- #
- # This function returns the generic root material ID for the given material type, where material types are "PLA",
- # "ABS", etc.
- #
- def getFallbackMaterialIdByMaterialType(self, material_type: str) -> Optional[str]:
- # For safety
- if material_type not in self._fallback_materials_map:
- Logger.log("w", "The material type [%s] does not have a fallback material" % material_type)
- return None
- fallback_material = self._fallback_materials_map[material_type]
- if fallback_material:
- return self.getRootMaterialIDWithoutDiameter(fallback_material["id"])
- else:
- return None
-
- ## Get default material for given global stack, extruder position and extruder nozzle name
- # you can provide the extruder_definition and then the position is ignored (useful when building up global stack in CuraStackBuilder)
- def getDefaultMaterial(self, global_stack: "GlobalStack", position: str, nozzle_name: Optional[str],
- extruder_definition: Optional["DefinitionContainer"] = None) -> Optional["MaterialNode"]:
- node = None
-
- buildplate_name = global_stack.getBuildplateName()
- machine_definition = global_stack.definition
-
- # The extruder-compatible material diameter in the extruder definition may not be the correct value because
- # the user can change it in the definition_changes container.
- if extruder_definition is None:
- extruder_stack_or_definition = global_stack.extruders[position]
- is_extruder_stack = True
- else:
- extruder_stack_or_definition = extruder_definition
- is_extruder_stack = False
-
- if extruder_stack_or_definition and parseBool(global_stack.getMetaDataEntry("has_materials", False)):
- if is_extruder_stack:
- material_diameter = extruder_stack_or_definition.getCompatibleMaterialDiameter()
- else:
- material_diameter = extruder_stack_or_definition.getProperty("material_diameter", "value")
-
- if isinstance(material_diameter, SettingFunction):
- material_diameter = material_diameter(global_stack)
- approximate_material_diameter = str(round(material_diameter))
- root_material_id = machine_definition.getMetaDataEntry("preferred_material")
- root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter)
- node = self.getMaterialNode(machine_definition.getId(), nozzle_name, buildplate_name,
- material_diameter, root_material_id)
- return node
-
- def removeMaterialByRootId(self, root_material_id: str):
- material_group = self.getMaterialGroup(root_material_id)
- if not material_group:
- Logger.log("i", "Unable to remove the material with id %s, because it doesn't exist.", root_material_id)
- return
-
- nodes_to_remove = [material_group.root_material_node] + material_group.derived_material_node_list
- # Sort all nodes with respect to the container ID lengths in the ascending order so the base material container
- # will be the first one to be removed. We need to do this to ensure that all containers get loaded & deleted.
- nodes_to_remove = sorted(nodes_to_remove, key = lambda x: len(x.getMetaDataEntry("id", "")))
- # Try to load all containers first. If there is any faulty ones, they will be put into the faulty container
- # list, so removeContainer() can ignore those ones.
- for node in nodes_to_remove:
- container_id = node.getMetaDataEntry("id", "")
- results = self._container_registry.findContainers(id = container_id)
- if not results:
- self._container_registry.addWrongContainerId(container_id)
- for node in nodes_to_remove:
- self._container_registry.removeContainer(node.getMetaDataEntry("id", ""))
-
- #
- # Methods for GUI
- #
-
- #
- # Sets the new name for the given material.
- #
- @pyqtSlot("QVariant", str)
- def setMaterialName(self, material_node: "MaterialNode", name: str) -> None:
- root_material_id = material_node.getMetaDataEntry("base_file")
- if root_material_id is None:
- return
- if self._container_registry.isReadOnly(root_material_id):
- Logger.log("w", "Cannot set name of read-only container %s.", root_material_id)
- return
-
- material_group = self.getMaterialGroup(root_material_id)
- if material_group:
- container = material_group.root_material_node.getContainer()
- if container:
- container.setName(name)
-
- #
- # Removes the given material.
- #
- @pyqtSlot("QVariant")
- def removeMaterial(self, material_node: "MaterialNode") -> None:
- root_material_id = material_node.getMetaDataEntry("base_file")
- if root_material_id is not None:
- self.removeMaterialByRootId(root_material_id)
-
- #
- # Creates a duplicate of a material, which has the same GUID and base_file metadata.
- # Returns the root material ID of the duplicated material if successful.
- #
- @pyqtSlot("QVariant", result = str)
- def duplicateMaterial(self, material_node: MaterialNode, new_base_id: Optional[str] = None, new_metadata: Dict[str, Any] = None) -> Optional[str]:
- root_material_id = cast(str, material_node.getMetaDataEntry("base_file", ""))
-
- material_group = self.getMaterialGroup(root_material_id)
- if not material_group:
- Logger.log("i", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id)
- return None
-
- base_container = material_group.root_material_node.getContainer()
- if not base_container:
- return None
-
- # Ensure all settings are saved.
- self._application.saveSettings()
-
- # Create a new ID & container to hold the data.
- new_containers = []
- if new_base_id is None:
- new_base_id = self._container_registry.uniqueName(base_container.getId())
- new_base_container = copy.deepcopy(base_container)
- new_base_container.getMetaData()["id"] = new_base_id
- new_base_container.getMetaData()["base_file"] = new_base_id
- if new_metadata is not None:
- for key, value in new_metadata.items():
- new_base_container.getMetaData()[key] = value
- new_containers.append(new_base_container)
-
- # Clone all of them.
- for node in material_group.derived_material_node_list:
- container_to_copy = node.getContainer()
- if not container_to_copy:
- continue
- # Create unique IDs for every clone.
- new_id = new_base_id
- if container_to_copy.getMetaDataEntry("definition") != "fdmprinter":
- new_id += "_" + container_to_copy.getMetaDataEntry("definition")
- if container_to_copy.getMetaDataEntry("variant_name"):
- nozzle_name = container_to_copy.getMetaDataEntry("variant_name")
- new_id += "_" + nozzle_name.replace(" ", "_")
-
- new_container = copy.deepcopy(container_to_copy)
- new_container.getMetaData()["id"] = new_id
- new_container.getMetaData()["base_file"] = new_base_id
- if new_metadata is not None:
- for key, value in new_metadata.items():
- new_container.getMetaData()[key] = value
-
- new_containers.append(new_container)
-
- for container_to_add in new_containers:
- container_to_add.setDirty(True)
- self._container_registry.addContainer(container_to_add)
-
- # if the duplicated material was favorite then the new material should also be added to favorite.
- if root_material_id in self.getFavorites():
- self.addFavorite(new_base_id)
-
- return new_base_id
-
- #
- # Create a new material by cloning Generic PLA for the current material diameter and generate a new GUID.
- # Returns the ID of the newly created material.
- @pyqtSlot(result = str)
- def createMaterial(self) -> str:
- from UM.i18n import i18nCatalog
- catalog = i18nCatalog("cura")
- # Ensure all settings are saved.
- self._application.saveSettings()
-
- machine_manager = self._application.getMachineManager()
- extruder_stack = machine_manager.activeStack
-
- machine_definition = self._application.getGlobalContainerStack().definition
- root_material_id = machine_definition.getMetaDataEntry("preferred_material", default = "generic_pla")
-
- approximate_diameter = str(extruder_stack.approximateMaterialDiameter)
- root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_diameter)
- material_group = self.getMaterialGroup(root_material_id)
-
- if not material_group: # This should never happen
- Logger.log("w", "Cannot get the material group of %s.", root_material_id)
- return ""
-
- # Create a new ID & container to hold the data.
- new_id = self._container_registry.uniqueName("custom_material")
- new_metadata = {"name": catalog.i18nc("@label", "Custom Material"),
- "brand": catalog.i18nc("@label", "Custom"),
- "GUID": str(uuid.uuid4()),
- }
-
- self.duplicateMaterial(material_group.root_material_node,
- new_base_id = new_id,
- new_metadata = new_metadata)
- return new_id
-
- @pyqtSlot(str)
- def addFavorite(self, root_material_id: str) -> None:
- self._favorites.add(root_material_id)
- self.materialsUpdated.emit()
-
- # Ensure all settings are saved.
- self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites)))
- self._application.saveSettings()
-
- @pyqtSlot(str)
- def removeFavorite(self, root_material_id: str) -> None:
- try:
- self._favorites.remove(root_material_id)
- except KeyError:
- Logger.log("w", "Could not delete material %s from favorites as it was already deleted", root_material_id)
- return
- self.materialsUpdated.emit()
-
- # Ensure all settings are saved.
- self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites)))
- self._application.saveSettings()
-
- @pyqtSlot()
- def getFavorites(self):
- return self._favorites
diff --git a/cura/Machines/MaterialNode.py b/cura/Machines/MaterialNode.py
index a4dcb0564f..fe20af2cd5 100644
--- a/cura/Machines/MaterialNode.py
+++ b/cura/Machines/MaterialNode.py
@@ -1,25 +1,136 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional, Dict, Any
-from collections import OrderedDict
-from .ContainerNode import ContainerNode
+from typing import Any, Optional, TYPE_CHECKING
+from UM.Logger import Logger
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Settings.Interfaces import ContainerInterface
+from UM.Signal import Signal
+from cura.Machines.ContainerNode import ContainerNode
+from cura.Machines.QualityNode import QualityNode
+import UM.FlameProfiler
+if TYPE_CHECKING:
+ from typing import Dict
+ from cura.Machines.VariantNode import VariantNode
+
+## Represents a material in the container tree.
#
-# A MaterialNode is a node in the material lookup tree/map/table. It contains 2 (extra) fields:
-# - material_map: a one-to-one map of "material_root_id" to material_node.
-# - children_map: the key-value map for child nodes of this node. This is used in a lookup tree.
-#
-#
+# Its subcontainers are quality profiles.
class MaterialNode(ContainerNode):
- __slots__ = ("material_map", "children_map")
+ def __init__(self, container_id: str, variant: "VariantNode") -> None:
+ super().__init__(container_id)
+ self.variant = variant
+ self.qualities = {} # type: Dict[str, QualityNode] # Mapping container IDs to quality profiles.
+ self.materialChanged = Signal() # Triggered when the material is removed or its metadata is updated.
- def __init__(self, metadata: Optional[Dict[str, Any]] = None) -> None:
- super().__init__(metadata = metadata)
- self.material_map = {} # type: Dict[str, MaterialNode] # material_root_id -> material_node
+ container_registry = ContainerRegistry.getInstance()
+ my_metadata = container_registry.findContainersMetadata(id = container_id)[0]
+ self.base_file = my_metadata["base_file"]
+ self.material_type = my_metadata["material"]
+ self.guid = my_metadata["GUID"]
+ self._loadAll()
+ container_registry.containerRemoved.connect(self._onRemoved)
+ container_registry.containerMetaDataChanged.connect(self._onMetadataChanged)
- # We overide this as we want to indicate that MaterialNodes can only contain other material nodes.
- self.children_map = OrderedDict() # type: OrderedDict[str, "MaterialNode"]
+ ## Finds the preferred quality for this printer with this material and this
+ # variant loaded.
+ #
+ # If the preferred quality is not available, an arbitrary quality is
+ # returned. If there is a configuration mistake (like a typo in the
+ # preferred quality) this returns a random available quality. If there are
+ # no available qualities, this will return the empty quality node.
+ # \return The node for the preferred quality, or any arbitrary quality if
+ # there is no match.
+ def preferredQuality(self) -> QualityNode:
+ for quality_id, quality_node in self.qualities.items():
+ if self.variant.machine.preferred_quality_type == quality_node.quality_type:
+ return quality_node
+ fallback = next(iter(self.qualities.values())) # Should only happen with empty quality node.
+ Logger.log("w", "Could not find preferred quality type {preferred_quality_type} for material {material_id} and variant {variant_id}, falling back to {fallback}.".format(
+ preferred_quality_type = self.variant.machine.preferred_quality_type,
+ material_id = self.container_id,
+ variant_id = self.variant.container_id,
+ fallback = fallback.container_id
+ ))
+ return fallback
- def getChildNode(self, child_key: str) -> Optional["MaterialNode"]:
- return self.children_map.get(child_key)
\ No newline at end of file
+ @UM.FlameProfiler.profile
+ def _loadAll(self) -> None:
+ container_registry = ContainerRegistry.getInstance()
+ # Find all quality profiles that fit on this material.
+ if not self.variant.machine.has_machine_quality: # Need to find the global qualities.
+ qualities = container_registry.findInstanceContainersMetadata(type = "quality", definition = "fdmprinter")
+ elif not self.variant.machine.has_materials:
+ qualities = container_registry.findInstanceContainersMetadata(type="quality", definition=self.variant.machine.quality_definition)
+ else:
+ if self.variant.machine.has_variants:
+ # Need to find the qualities that specify a material profile with the same material type.
+ qualities = container_registry.findInstanceContainersMetadata(type = "quality", definition = self.variant.machine.quality_definition, variant = self.variant.variant_name, material = self.container_id) # First try by exact material ID.
+ else:
+ qualities = container_registry.findInstanceContainersMetadata(type="quality", definition=self.variant.machine.quality_definition, material=self.container_id)
+ if not qualities:
+ my_material_type = self.material_type
+ if self.variant.machine.has_variants:
+ qualities_any_material = container_registry.findInstanceContainersMetadata(type = "quality", definition = self.variant.machine.quality_definition, variant = self.variant.variant_name)
+ else:
+ qualities_any_material = container_registry.findInstanceContainersMetadata(type="quality", definition = self.variant.machine.quality_definition)
+ for material_metadata in container_registry.findInstanceContainersMetadata(type = "material", material = my_material_type):
+ qualities.extend((quality for quality in qualities_any_material if quality.get("material") == material_metadata["id"]))
+
+ if not qualities: # No quality profiles found. Go by GUID then.
+ my_guid = self.guid
+ for material_metadata in container_registry.findInstanceContainersMetadata(type = "material", guid = my_guid):
+ qualities.extend((quality for quality in qualities_any_material if quality["material"] == material_metadata["id"]))
+
+ if not qualities:
+ # There are still some machines that should use global profiles in the extruder, so do that now.
+ # These are mostly older machines that haven't received updates (so single extruder machines without specific qualities
+ # but that do have materials and profiles specific to that machine)
+ qualities.extend([quality for quality in qualities_any_material if quality.get("global_quality", "False") != "False"])
+
+ for quality in qualities:
+ quality_id = quality["id"]
+ if quality_id not in self.qualities:
+ self.qualities[quality_id] = QualityNode(quality_id, parent = self)
+ if not self.qualities:
+ self.qualities["empty_quality"] = QualityNode("empty_quality", parent = self)
+
+ ## Triggered when any container is removed, but only handles it when the
+ # container is removed that this node represents.
+ # \param container The container that was allegedly removed.
+ def _onRemoved(self, container: ContainerInterface) -> None:
+ if container.getId() == self.container_id:
+ # Remove myself from my parent.
+ if self.base_file in self.variant.materials:
+ del self.variant.materials[self.base_file]
+ if not self.variant.materials:
+ self.variant.materials["empty_material"] = MaterialNode("empty_material", variant = self.variant)
+ self.materialChanged.emit(self)
+
+ ## Triggered when any metadata changed in any container, but only handles
+ # it when the metadata of this node is changed.
+ # \param container The container whose metadata changed.
+ # \param kwargs Key-word arguments provided when changing the metadata.
+ # These are ignored. As far as I know they are never provided to this
+ # call.
+ def _onMetadataChanged(self, container: ContainerInterface, **kwargs: Any) -> None:
+ if container.getId() != self.container_id:
+ return
+
+ new_metadata = container.getMetaData()
+ old_base_file = self.base_file
+ if new_metadata["base_file"] != old_base_file:
+ self.base_file = new_metadata["base_file"]
+ if old_base_file in self.variant.materials: # Move in parent node.
+ del self.variant.materials[old_base_file]
+ self.variant.materials[self.base_file] = self
+
+ old_material_type = self.material_type
+ self.material_type = new_metadata["material"]
+ old_guid = self.guid
+ self.guid = new_metadata["GUID"]
+ if self.base_file != old_base_file or self.material_type != old_material_type or self.guid != old_guid: # List of quality profiles could've changed.
+ self.qualities = {}
+ self._loadAll() # Re-load the quality profiles for this node.
+ self.materialChanged.emit(self)
diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py
index e936877923..db660704b5 100644
--- a/cura/Machines/Models/BaseMaterialsModel.py
+++ b/cura/Machines/Models/BaseMaterialsModel.py
@@ -1,18 +1,22 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional, Dict, Set
-from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
+from typing import Dict, Set
+
+from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtProperty
+
from UM.Qt.ListModel import ListModel
+from UM.Logger import Logger
+import cura.CuraApplication # Imported like this to prevent a circular reference.
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Machines.MaterialNode import MaterialNode
+from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
## This is the base model class for GenericMaterialsModel and MaterialBrandsModel.
# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately.
# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top
# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu
-from cura.Machines.MaterialNode import MaterialNode
-
-
class BaseMaterialsModel(ListModel):
extruderPositionChanged = pyqtSignal()
@@ -24,19 +28,36 @@ class BaseMaterialsModel(ListModel):
self._application = CuraApplication.getInstance()
+ self._available_materials = {} # type: Dict[str, MaterialNode]
+ self._favorite_ids = set() # type: Set[str]
+
# Make these managers available to all material models
self._container_registry = self._application.getInstance().getContainerRegistry()
self._machine_manager = self._application.getMachineManager()
- self._material_manager = self._application.getMaterialManager()
+
+ self._extruder_position = 0
+ self._extruder_stack = None
+ self._enabled = True
+
+ # CURA-6904
+ # Updating the material model requires information from material nodes and containers. We use a timer here to
+ # make sure that an update function call will not be directly invoked by an event. Because the triggered event
+ # can be caused in the middle of a XMLMaterial loading, and the material container we try to find may not be
+ # in the system yet. This will cause an infinite recursion of (1) trying to load a material, (2) trying to
+ # update the material model, (3) cannot find the material container, load it, (4) repeat #1.
+ self._update_timer = QTimer()
+ self._update_timer.setInterval(100)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._update)
# Update the stack and the model data when the machine changes
self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack)
+ self._updateExtruderStack()
- # Update this model when switching machines
- self._machine_manager.activeStackChanged.connect(self._update)
-
- # Update this model when list of materials changes
- self._material_manager.materialsUpdated.connect(self._update)
+ # Update this model when switching machines or tabs, when adding materials or changing their metadata.
+ self._machine_manager.activeStackChanged.connect(self._onChanged)
+ ContainerTree.getInstance().materialsChanged.connect(self._materialsListChanged)
+ self._application.getMaterialManagementModel().favoritesChanged.connect(self._onChanged)
self.addRoleName(Qt.UserRole + 1, "root_material_id")
self.addRoleName(Qt.UserRole + 2, "id")
@@ -55,12 +76,8 @@ class BaseMaterialsModel(ListModel):
self.addRoleName(Qt.UserRole + 15, "container_node")
self.addRoleName(Qt.UserRole + 16, "is_favorite")
- self._extruder_position = 0
- self._extruder_stack = None
-
- self._available_materials = None # type: Optional[Dict[str, MaterialNode]]
- self._favorite_ids = set() # type: Set[str]
- self._enabled = True
+ def _onChanged(self) -> None:
+ self._update_timer.start()
def _updateExtruderStack(self):
global_stack = self._machine_manager.activeMachine
@@ -68,14 +85,19 @@ class BaseMaterialsModel(ListModel):
return
if self._extruder_stack is not None:
- self._extruder_stack.pyqtContainersChanged.disconnect(self._update)
- self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._update)
- self._extruder_stack = global_stack.extruders.get(str(self._extruder_position))
+ self._extruder_stack.pyqtContainersChanged.disconnect(self._onChanged)
+ self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._onChanged)
+
+ try:
+ self._extruder_stack = global_stack.extruderList[self._extruder_position]
+ except IndexError:
+ self._extruder_stack = None
+
if self._extruder_stack is not None:
- self._extruder_stack.pyqtContainersChanged.connect(self._update)
- self._extruder_stack.approximateMaterialDiameterChanged.connect(self._update)
+ self._extruder_stack.pyqtContainersChanged.connect(self._onChanged)
+ self._extruder_stack.approximateMaterialDiameterChanged.connect(self._onChanged)
# Force update the model when the extruder stack changes
- self._update()
+ self._onChanged()
def setExtruderPosition(self, position: int):
if self._extruder_stack is None or self._extruder_position != position:
@@ -92,43 +114,76 @@ class BaseMaterialsModel(ListModel):
self._enabled = enabled
if self._enabled:
# ensure the data is there again.
- self._update()
+ self._onChanged()
self.enabledChanged.emit()
- @pyqtProperty(bool, fset=setEnabled, notify=enabledChanged)
+ @pyqtProperty(bool, fset = setEnabled, notify = enabledChanged)
def enabled(self):
return self._enabled
- ## This is an abstract method that needs to be implemented by the specific
- # models themselves.
+ ## Triggered when a list of materials changed somewhere in the container
+ # tree. This change may trigger an _update() call when the materials
+ # changed for the configuration that this model is looking for.
+ def _materialsListChanged(self, material: MaterialNode) -> None:
+ if self._extruder_stack is None:
+ return
+ if material.variant.container_id != self._extruder_stack.variant.getId():
+ return
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack:
+ return
+ if material.variant.machine.container_id != global_stack.definition.getId():
+ return
+ self._onChanged()
+
+ ## Triggered when the list of favorite materials is changed.
+ def _favoritesChanged(self, material_base_file: str) -> None:
+ if material_base_file in self._available_materials:
+ self._onChanged()
+
+ ## This is an abstract method that needs to be implemented by the specific
+ # models themselves.
def _update(self):
- pass
+ self._favorite_ids = set(cura.CuraApplication.CuraApplication.getInstance().getPreferences().getValue("cura/favorite_materials").split(";"))
+
+ # Update the available materials (ContainerNode) for the current active machine and extruder setup.
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack.hasMaterials:
+ return # There are no materials for this machine, so nothing to do.
+ extruder_stack = global_stack.extruders.get(str(self._extruder_position))
+ if not extruder_stack:
+ return
+ nozzle_name = extruder_stack.variant.getName()
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
+ if nozzle_name not in machine_node.variants:
+ Logger.log("w", "Unable to find variant %s in container tree", nozzle_name)
+ self._available_materials = {}
+ return
+ materials = machine_node.variants[nozzle_name].materials
+ approximate_material_diameter = extruder_stack.getApproximateMaterialDiameter()
+ self._available_materials = {key: material for key, material in materials.items() if float(material.getMetaDataEntry("approximate_diameter", -1)) == approximate_material_diameter}
## This method is used by all material models in the beginning of the
# _update() method in order to prevent errors. It's the same in all models
# so it's placed here for easy access.
def _canUpdate(self):
global_stack = self._machine_manager.activeMachine
-
if global_stack is None or not self._enabled:
return False
extruder_position = str(self._extruder_position)
-
if extruder_position not in global_stack.extruders:
return False
-
- extruder_stack = global_stack.extruders[extruder_position]
- self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
- if self._available_materials is None:
- return False
return True
## This is another convenience function which is shared by all material
# models so it's put here to avoid having so much duplicated code.
def _createMaterialItem(self, root_material_id, container_node):
- metadata = container_node.getMetadata()
+ metadata_list = CuraContainerRegistry.getInstance().findContainersMetadata(id = container_node.container_id)
+ if not metadata_list:
+ return None
+ metadata = metadata_list[0]
item = {
"root_material_id": root_material_id,
"id": metadata["id"],
@@ -149,4 +204,3 @@ class BaseMaterialsModel(ListModel):
"is_favorite": root_material_id in self._favorite_ids
}
return item
-
diff --git a/cura/Machines/Models/BuildPlateModel.py b/cura/Machines/Models/BuildPlateModel.py
index 82b9db4d64..3697dd2762 100644
--- a/cura/Machines/Models/BuildPlateModel.py
+++ b/cura/Machines/Models/BuildPlateModel.py
@@ -1,14 +1,9 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt
-
-from UM.Application import Application
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
-from UM.Util import parseBool
-
-from cura.Machines.VariantType import VariantType
class BuildPlateModel(ListModel):
@@ -21,31 +16,9 @@ class BuildPlateModel(ListModel):
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.ContainerNodeRole, "container_node")
- self._application = Application.getInstance()
- self._variant_manager = self._application._variant_manager
- self._machine_manager = self._application.getMachineManager()
-
- self._machine_manager.globalContainerChanged.connect(self._update)
-
self._update()
def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
- global_stack = self._machine_manager._global_container_stack
- if not global_stack:
- self.setItems([])
- return
-
- has_variants = parseBool(global_stack.getMetaDataEntry("has_variant_buildplates", False))
- if not has_variants:
- self.setItems([])
- return
-
- variant_dict = self._variant_manager.getVariantNodes(global_stack, variant_type = VariantType.BUILD_PLATE)
-
- item_list = []
- for name, variant_node in variant_dict.items():
- item = {"name": name,
- "container_node": variant_node}
- item_list.append(item)
- self.setItems(item_list)
+ self.setItems([])
+ return
diff --git a/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py
index dcade8cb0d..1ab7e21700 100644
--- a/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py
+++ b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py
@@ -1,31 +1,48 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional, TYPE_CHECKING
+
from UM.Logger import Logger
+import cura.CuraApplication # Imported this way to prevent circular references.
+from cura.Machines.ContainerTree import ContainerTree
from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel
+if TYPE_CHECKING:
+ from PyQt5.QtCore import QObject
+ from UM.Settings.Interfaces import ContainerInterface
-#
-# This model is used for the custom profile items in the profile drop down menu.
-#
+
+## This model is used for the custom profile items in the profile drop down
+# menu.
class CustomQualityProfilesDropDownMenuModel(QualityProfilesDropDownMenuModel):
- def _update(self):
+ def __init__(self, parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ container_registry.containerAdded.connect(self._qualityChangesListChanged)
+ container_registry.containerRemoved.connect(self._qualityChangesListChanged)
+ container_registry.containerMetaDataChanged.connect(self._qualityChangesListChanged)
+
+ def _qualityChangesListChanged(self, container: "ContainerInterface") -> None:
+ if container.getMetaDataEntry("type") == "quality_changes":
+ self._update()
+
+ def _update(self) -> None:
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
- active_global_stack = self._machine_manager.activeMachine
+ active_global_stack = cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeMachine
if active_global_stack is None:
self.setItems([])
Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__)
return
- quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(active_global_stack)
+ quality_changes_list = ContainerTree.getInstance().getCurrentQualityChangesGroups()
item_list = []
- for key in sorted(quality_changes_group_dict, key = lambda name: name.upper()):
- quality_changes_group = quality_changes_group_dict[key]
-
+ for quality_changes_group in sorted(quality_changes_list, key = lambda qgc: qgc.name.lower()):
item = {"name": quality_changes_group.name,
"layer_height": "",
"layer_height_without_unit": "",
diff --git a/cura/Machines/Models/DiscoveredPrintersModel.py b/cura/Machines/Models/DiscoveredPrintersModel.py
new file mode 100644
index 0000000000..c662334470
--- /dev/null
+++ b/cura/Machines/Models/DiscoveredPrintersModel.py
@@ -0,0 +1,263 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Callable, Dict, List, Optional, TYPE_CHECKING
+
+from PyQt5.QtCore import pyqtSlot, pyqtProperty, pyqtSignal, QObject, QTimer
+
+from UM.i18n import i18nCatalog
+from UM.Logger import Logger
+from UM.Util import parseBool
+from UM.OutputDevice.OutputDeviceManager import ManualDeviceAdditionAttempt
+
+if TYPE_CHECKING:
+ from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
+ from cura.CuraApplication import CuraApplication
+ from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice
+
+
+catalog = i18nCatalog("cura")
+
+
+class DiscoveredPrinter(QObject):
+
+ def __init__(self, ip_address: str, key: str, name: str, create_callback: Callable[[str], None], machine_type: str,
+ device: "NetworkedPrinterOutputDevice", parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+
+ self._ip_address = ip_address
+ self._key = key
+ self._name = name
+ self.create_callback = create_callback
+ self._machine_type = machine_type
+ self._device = device
+
+ nameChanged = pyqtSignal()
+
+ def getKey(self) -> str:
+ return self._key
+
+ @pyqtProperty(str, notify = nameChanged)
+ def name(self) -> str:
+ return self._name
+
+ def setName(self, name: str) -> None:
+ if self._name != name:
+ self._name = name
+ self.nameChanged.emit()
+
+ @pyqtProperty(str, constant = True)
+ def address(self) -> str:
+ return self._ip_address
+
+ machineTypeChanged = pyqtSignal()
+
+ @pyqtProperty(str, notify = machineTypeChanged)
+ def machineType(self) -> str:
+ return self._machine_type
+
+ def setMachineType(self, machine_type: str) -> None:
+ if self._machine_type != machine_type:
+ self._machine_type = machine_type
+ self.machineTypeChanged.emit()
+
+ # Checks if the given machine type name in the available machine list.
+ # The machine type is a code name such as "ultimaker_3", while the machine type name is the human-readable name of
+ # the machine type, which is "Ultimaker 3" for "ultimaker_3".
+ def _hasHumanReadableMachineTypeName(self, machine_type_name: str) -> bool:
+ from cura.CuraApplication import CuraApplication
+ results = CuraApplication.getInstance().getContainerRegistry().findDefinitionContainersMetadata(name = machine_type_name)
+ return len(results) > 0
+
+ # Human readable machine type string
+ @pyqtProperty(str, notify = machineTypeChanged)
+ def readableMachineType(self) -> str:
+ from cura.CuraApplication import CuraApplication
+ machine_manager = CuraApplication.getInstance().getMachineManager()
+ # In NetworkOutputDevice, when it updates a printer information, it updates the machine type using the field
+ # "machine_variant", and for some reason, it's not the machine type ID/codename/... but a human-readable string
+ # like "Ultimaker 3". The code below handles this case.
+ if self._hasHumanReadableMachineTypeName(self._machine_type):
+ readable_type = self._machine_type
+ else:
+ readable_type = self._getMachineTypeNameFromId(self._machine_type)
+ if not readable_type:
+ readable_type = catalog.i18nc("@label", "Unknown")
+ return readable_type
+
+ @pyqtProperty(bool, notify = machineTypeChanged)
+ def isUnknownMachineType(self) -> bool:
+ if self._hasHumanReadableMachineTypeName(self._machine_type):
+ readable_type = self._machine_type
+ else:
+ readable_type = self._getMachineTypeNameFromId(self._machine_type)
+ return not readable_type
+
+ def _getMachineTypeNameFromId(self, machine_type_id: str) -> str:
+ machine_type_name = ""
+ from cura.CuraApplication import CuraApplication
+ results = CuraApplication.getInstance().getContainerRegistry().findDefinitionContainersMetadata(id = machine_type_id)
+ if results:
+ machine_type_name = results[0]["name"]
+ return machine_type_name
+
+ @pyqtProperty(QObject, constant = True)
+ def device(self) -> "NetworkedPrinterOutputDevice":
+ return self._device
+
+ @pyqtProperty(bool, constant = True)
+ def isHostOfGroup(self) -> bool:
+ return getattr(self._device, "clusterSize", 1) > 0
+
+ @pyqtProperty(str, constant = True)
+ def sectionName(self) -> str:
+ if self.isUnknownMachineType or not self.isHostOfGroup:
+ return catalog.i18nc("@label", "The printer(s) below cannot be connected because they are part of a group")
+ else:
+ return catalog.i18nc("@label", "Available networked printers")
+
+
+#
+# Discovered printers are all the printers that were found on the network, which provide a more convenient way
+# to add networked printers (Plugin finds a bunch of printers, user can select one from the list, plugin can then
+# add that printer to Cura as the active one).
+#
+class DiscoveredPrintersModel(QObject):
+
+ def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+
+ self._application = application
+ self._discovered_printer_by_ip_dict = dict() # type: Dict[str, DiscoveredPrinter]
+
+ self._plugin_for_manual_device = None # type: Optional[OutputDevicePlugin]
+ self._manual_device_address = ""
+
+ self._manual_device_request_timeout_in_seconds = 5 # timeout for adding a manual device in seconds
+ self._manual_device_request_timer = QTimer()
+ self._manual_device_request_timer.setInterval(self._manual_device_request_timeout_in_seconds * 1000)
+ self._manual_device_request_timer.setSingleShot(True)
+ self._manual_device_request_timer.timeout.connect(self._onManualRequestTimeout)
+
+ discoveredPrintersChanged = pyqtSignal()
+
+ @pyqtSlot(str)
+ def checkManualDevice(self, address: str) -> None:
+ if self.hasManualDeviceRequestInProgress:
+ Logger.log("i", "A manual device request for address [%s] is still in progress, do nothing",
+ self._manual_device_address)
+ return
+
+ priority_order = [
+ ManualDeviceAdditionAttempt.PRIORITY,
+ ManualDeviceAdditionAttempt.POSSIBLE,
+ ] # type: List[ManualDeviceAdditionAttempt]
+
+ all_plugins_dict = self._application.getOutputDeviceManager().getAllOutputDevicePlugins()
+
+ can_add_manual_plugins = [item for item in filter(
+ lambda plugin_item: plugin_item.canAddManualDevice(address) in priority_order,
+ all_plugins_dict.values())]
+
+ if not can_add_manual_plugins:
+ Logger.log("d", "Could not find a plugin to accept adding %s manually via address.", address)
+ return
+
+ plugin = max(can_add_manual_plugins, key = lambda p: priority_order.index(p.canAddManualDevice(address)))
+ self._plugin_for_manual_device = plugin
+ self._plugin_for_manual_device.addManualDevice(address, callback = self._onManualDeviceRequestFinished)
+ self._manual_device_address = address
+ self._manual_device_request_timer.start()
+ self.hasManualDeviceRequestInProgressChanged.emit()
+
+ @pyqtSlot()
+ def cancelCurrentManualDeviceRequest(self) -> None:
+ self._manual_device_request_timer.stop()
+
+ if self._manual_device_address:
+ if self._plugin_for_manual_device is not None:
+ self._plugin_for_manual_device.removeManualDevice(self._manual_device_address, address = self._manual_device_address)
+ self._manual_device_address = ""
+ self._plugin_for_manual_device = None
+ self.hasManualDeviceRequestInProgressChanged.emit()
+ self.manualDeviceRequestFinished.emit(False)
+
+ def _onManualRequestTimeout(self) -> None:
+ Logger.log("w", "Manual printer [%s] request timed out. Cancel the current request.", self._manual_device_address)
+ self.cancelCurrentManualDeviceRequest()
+
+ hasManualDeviceRequestInProgressChanged = pyqtSignal()
+
+ @pyqtProperty(bool, notify = hasManualDeviceRequestInProgressChanged)
+ def hasManualDeviceRequestInProgress(self) -> bool:
+ return self._manual_device_address != ""
+
+ manualDeviceRequestFinished = pyqtSignal(bool, arguments = ["success"])
+
+ def _onManualDeviceRequestFinished(self, success: bool, address: str) -> None:
+ self._manual_device_request_timer.stop()
+ if address == self._manual_device_address:
+ self._manual_device_address = ""
+ self.hasManualDeviceRequestInProgressChanged.emit()
+ self.manualDeviceRequestFinished.emit(success)
+
+ @pyqtProperty("QVariantMap", notify = discoveredPrintersChanged)
+ def discoveredPrintersByAddress(self) -> Dict[str, DiscoveredPrinter]:
+ return self._discovered_printer_by_ip_dict
+
+ @pyqtProperty("QVariantList", notify = discoveredPrintersChanged)
+ def discoveredPrinters(self) -> List["DiscoveredPrinter"]:
+ item_list = list(
+ x for x in self._discovered_printer_by_ip_dict.values() if not parseBool(x.device.getProperty("temporary")))
+
+ # Split the printers into 2 lists and sort them ascending based on names.
+ available_list = []
+ not_available_list = []
+ for item in item_list:
+ if item.isUnknownMachineType or getattr(item.device, "clusterSize", 1) < 1:
+ not_available_list.append(item)
+ else:
+ available_list.append(item)
+
+ available_list.sort(key = lambda x: x.device.name)
+ not_available_list.sort(key = lambda x: x.device.name)
+
+ return available_list + not_available_list
+
+ def addDiscoveredPrinter(self, ip_address: str, key: str, name: str, create_callback: Callable[[str], None],
+ machine_type: str, device: "NetworkedPrinterOutputDevice") -> None:
+ if ip_address in self._discovered_printer_by_ip_dict:
+ Logger.log("e", "Printer with ip [%s] has already been added", ip_address)
+ return
+
+ discovered_printer = DiscoveredPrinter(ip_address, key, name, create_callback, machine_type, device, parent = self)
+ self._discovered_printer_by_ip_dict[ip_address] = discovered_printer
+ self.discoveredPrintersChanged.emit()
+
+ def updateDiscoveredPrinter(self, ip_address: str,
+ name: Optional[str] = None,
+ machine_type: Optional[str] = None) -> None:
+ if ip_address not in self._discovered_printer_by_ip_dict:
+ Logger.log("w", "Printer with ip [%s] is not known", ip_address)
+ return
+
+ item = self._discovered_printer_by_ip_dict[ip_address]
+
+ if name is not None:
+ item.setName(name)
+ if machine_type is not None:
+ item.setMachineType(machine_type)
+
+ def removeDiscoveredPrinter(self, ip_address: str) -> None:
+ if ip_address not in self._discovered_printer_by_ip_dict:
+ Logger.log("w", "Key [%s] does not exist in the discovered printers list.", ip_address)
+ return
+
+ del self._discovered_printer_by_ip_dict[ip_address]
+ self.discoveredPrintersChanged.emit()
+
+ # A convenience function for QML to create a machine (GlobalStack) out of the given discovered printer.
+ # This function invokes the given discovered printer's "create_callback" to do this.
+ @pyqtSlot("QVariant")
+ def createMachineFromDiscoveredPrinter(self, discovered_printer: "DiscoveredPrinter") -> None:
+ discovered_printer.create_callback(discovered_printer.getKey())
diff --git a/cura/Settings/ExtrudersModel.py b/cura/Machines/Models/ExtrudersModel.py
similarity index 97%
rename from cura/Settings/ExtrudersModel.py
rename to cura/Machines/Models/ExtrudersModel.py
index 93cc1ce402..9eee7f5f9e 100644
--- a/cura/Settings/ExtrudersModel.py
+++ b/cura/Machines/Models/ExtrudersModel.py
@@ -2,23 +2,25 @@
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
-from typing import Iterable
+from typing import Iterable, TYPE_CHECKING
from UM.i18n import i18nCatalog
-import UM.Qt.ListModel
+from UM.Qt.ListModel import ListModel
from UM.Application import Application
import UM.FlameProfiler
-from cura.Settings.ExtruderStack import ExtruderStack # To listen to changes on the extruders.
+if TYPE_CHECKING:
+ from cura.Settings.ExtruderStack import ExtruderStack # To listen to changes on the extruders.
catalog = i18nCatalog("cura")
+
## Model that holds extruders.
#
# This model is designed for use by any list of extruders, but specifically
# intended for drop-down lists of the current machine's extruders in place of
# settings.
-class ExtrudersModel(UM.Qt.ListModel.ListModel):
+class ExtrudersModel(ListModel):
# The ID of the container stack for the extruder.
IdRole = Qt.UserRole + 1
diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py
index 98a2a01597..6b8f0e8e56 100644
--- a/cura/Machines/Models/FavoriteMaterialsModel.py
+++ b/cura/Machines/Models/FavoriteMaterialsModel.py
@@ -1,28 +1,33 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
+import cura.CuraApplication # To listen to changes to the preferences.
## Model that shows the list of favorite materials.
class FavoriteMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
- self._update()
+ cura.CuraApplication.CuraApplication.getInstance().getPreferences().preferenceChanged.connect(self._onFavoritesChanged)
+ self._onChanged()
+
+ ## Triggered when any preference changes, but only handles it when the list
+ # of favourites is changed.
+ def _onFavoritesChanged(self, preference_key: str) -> None:
+ if preference_key != "cura/favorite_materials":
+ return
+ self._onChanged()
def _update(self):
if not self._canUpdate():
return
-
- # Get updated list of favorites
- self._favorite_ids = self._material_manager.getFavorites()
+ super()._update()
item_list = []
for root_material_id, container_node in self._available_materials.items():
- metadata = container_node.getMetadata()
-
# Do not include the materials from a to-be-removed package
- if bool(metadata.get("removed", False)):
+ if bool(container_node.getMetaDataEntry("removed", False)):
continue
# Only add results for favorite materials
@@ -30,7 +35,8 @@ class FavoriteMaterialsModel(BaseMaterialsModel):
continue
item = self._createMaterialItem(root_material_id, container_node)
- item_list.append(item)
+ if item:
+ item_list.append(item)
# Sort the item list alphabetically by name
item_list = sorted(item_list, key = lambda d: d["brand"].upper())
diff --git a/cura/Machines/Models/FirstStartMachineActionsModel.py b/cura/Machines/Models/FirstStartMachineActionsModel.py
new file mode 100644
index 0000000000..92caed7b12
--- /dev/null
+++ b/cura/Machines/Models/FirstStartMachineActionsModel.py
@@ -0,0 +1,112 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional, Dict, Any, TYPE_CHECKING
+
+from PyQt5.QtCore import QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot
+
+from UM.Qt.ListModel import ListModel
+
+if TYPE_CHECKING:
+ from cura.CuraApplication import CuraApplication
+
+
+#
+# This model holds all first-start machine actions for the currently active machine. It has 2 roles:
+# - title : the title/name of the action
+# - content : the QObject of the QML content of the action
+# - action : the MachineAction object itself
+#
+class FirstStartMachineActionsModel(ListModel):
+
+ TitleRole = Qt.UserRole + 1
+ ContentRole = Qt.UserRole + 2
+ ActionRole = Qt.UserRole + 3
+
+ def __init__(self, application: "CuraApplication", parent: Optional[QObject] = None) -> None:
+ super().__init__(parent)
+
+ self.addRoleName(self.TitleRole, "title")
+ self.addRoleName(self.ContentRole, "content")
+ self.addRoleName(self.ActionRole, "action")
+
+ self._current_action_index = 0
+
+ self._application = application
+ self._application.initializationFinished.connect(self.initialize)
+
+ self._previous_global_stack = None
+
+ def initialize(self) -> None:
+ self._application.getMachineManager().globalContainerChanged.connect(self._update)
+ self._update()
+
+ currentActionIndexChanged = pyqtSignal()
+ allFinished = pyqtSignal() # Emitted when all actions have been finished.
+
+ @pyqtProperty(int, notify = currentActionIndexChanged)
+ def currentActionIndex(self) -> int:
+ return self._current_action_index
+
+ @pyqtProperty("QVariantMap", notify = currentActionIndexChanged)
+ def currentItem(self) -> Optional[Dict[str, Any]]:
+ if self._current_action_index >= self.count:
+ return dict()
+ else:
+ return self.getItem(self._current_action_index)
+
+ @pyqtProperty(bool, notify = currentActionIndexChanged)
+ def hasMoreActions(self) -> bool:
+ return self._current_action_index < self.count - 1
+
+ @pyqtSlot()
+ def goToNextAction(self) -> None:
+ # finish the current item
+ if "action" in self.currentItem:
+ self.currentItem["action"].setFinished()
+
+ if not self.hasMoreActions:
+ self.allFinished.emit()
+ self.reset()
+ return
+
+ self._current_action_index += 1
+ self.currentActionIndexChanged.emit()
+
+ # Resets the current action index to 0 so the wizard panel can show actions from the beginning.
+ @pyqtSlot()
+ def reset(self) -> None:
+ self._current_action_index = 0
+ self.currentActionIndexChanged.emit()
+
+ if self.count == 0:
+ self.allFinished.emit()
+
+ def _update(self) -> None:
+ global_stack = self._application.getMachineManager().activeMachine
+ if global_stack is None:
+ self.setItems([])
+ return
+
+ # Do not update if the machine has not been switched. This can cause the SettingProviders on the Machine
+ # Setting page to do a force update, but they can use potential outdated cached values.
+ if self._previous_global_stack is not None and global_stack.getId() == self._previous_global_stack.getId():
+ return
+ self._previous_global_stack = global_stack
+
+ definition_id = global_stack.definition.getId()
+ first_start_actions = self._application.getMachineActionManager().getFirstStartActions(definition_id)
+
+ item_list = []
+ for item in first_start_actions:
+ item_list.append({"title": item.label,
+ "content": item.getDisplayItem(),
+ "action": item,
+ })
+ item.reset()
+
+ self.setItems(item_list)
+ self.reset()
+
+
+__all__ = ["FirstStartMachineActionsModel"]
diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py
index 8f41dd6a70..9ed1632b87 100644
--- a/cura/Machines/Models/GenericMaterialsModel.py
+++ b/cura/Machines/Models/GenericMaterialsModel.py
@@ -1,37 +1,33 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from UM.Logger import Logger
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
class GenericMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
- self._update()
+ self._onChanged()
def _update(self):
if not self._canUpdate():
return
-
- # Get updated list of favorites
- self._favorite_ids = self._material_manager.getFavorites()
+ super()._update()
item_list = []
for root_material_id, container_node in self._available_materials.items():
- metadata = container_node.getMetadata()
-
# Do not include the materials from a to-be-removed package
- if bool(metadata.get("removed", False)):
+ if bool(container_node.getMetaDataEntry("removed", False)):
continue
# Only add results for generic materials
- if metadata["brand"].lower() != "generic":
+ if container_node.getMetaDataEntry("brand", "unknown").lower() != "generic":
continue
item = self._createMaterialItem(root_material_id, container_node)
- item_list.append(item)
+ if item:
+ item_list.append(item)
# Sort the item list alphabetically by name
item_list = sorted(item_list, key = lambda d: d["name"].upper())
diff --git a/cura/GlobalStacksModel.py b/cura/Machines/Models/GlobalStacksModel.py
similarity index 68%
rename from cura/GlobalStacksModel.py
rename to cura/Machines/Models/GlobalStacksModel.py
index 3c3321e5ca..9db4ffe6db 100644
--- a/cura/GlobalStacksModel.py
+++ b/cura/Machines/Models/GlobalStacksModel.py
@@ -1,14 +1,14 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from PyQt5.QtCore import Qt, QTimer
from UM.Qt.ListModel import ListModel
+from UM.i18n import i18nCatalog
+from UM.Util import parseBool
-from PyQt5.QtCore import pyqtProperty, Qt, QTimer
-
-from cura.PrinterOutputDevice import ConnectionType
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
-
from cura.Settings.GlobalStack import GlobalStack
@@ -18,14 +18,18 @@ class GlobalStacksModel(ListModel):
HasRemoteConnectionRole = Qt.UserRole + 3
ConnectionTypeRole = Qt.UserRole + 4
MetaDataRole = Qt.UserRole + 5
+ DiscoverySourceRole = Qt.UserRole + 6 # For separating local and remote printers in the machine management page
- def __init__(self, parent = None):
+ def __init__(self, parent = None) -> None:
super().__init__(parent)
+
+ self._catalog = i18nCatalog("cura")
+
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
self.addRoleName(self.MetaDataRole, "metadata")
- self._container_stacks = []
+ self.addRoleName(self.DiscoverySourceRole, "discoverySource")
self._change_timer = QTimer()
self._change_timer.setInterval(200)
@@ -36,35 +40,38 @@ class GlobalStacksModel(ListModel):
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
- self._filter_dict = {}
self._updateDelayed()
## Handler for container added/removed events from registry
- def _onContainerChanged(self, container):
+ def _onContainerChanged(self, container) -> None:
# We only need to update when the added / removed container GlobalStack
if isinstance(container, GlobalStack):
self._updateDelayed()
- def _updateDelayed(self):
+ def _updateDelayed(self) -> None:
self._change_timer.start()
def _update(self) -> None:
items = []
container_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine")
-
for container_stack in container_stacks:
has_remote_connection = False
for connection_type in container_stack.configuredConnectionTypes:
- has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
+ has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
+ ConnectionType.CloudConnection.value]
- if container_stack.getMetaDataEntry("hidden", False) in ["True", True]:
+ if parseBool(container_stack.getMetaDataEntry("hidden", False)):
continue
+ section_name = "Network enabled printers" if has_remote_connection else "Local printers"
+ section_name = self._catalog.i18nc("@info:title", section_name)
+
items.append({"name": container_stack.getMetaDataEntry("group_name", container_stack.getName()),
"id": container_stack.getId(),
"hasRemoteConnection": has_remote_connection,
- "metadata": container_stack.getMetaData().copy()})
- items.sort(key=lambda i: not i["hasRemoteConnection"])
+ "metadata": container_stack.getMetaData().copy(),
+ "discoverySource": section_name})
+ items.sort(key = lambda i: (not i["hasRemoteConnection"], i["name"]))
self.setItems(items)
diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py
new file mode 100644
index 0000000000..202d79bb15
--- /dev/null
+++ b/cura/Machines/Models/IntentCategoryModel.py
@@ -0,0 +1,118 @@
+#Copyright (c) 2019 Ultimaker B.V.
+#Cura is released under the terms of the LGPLv3 or higher.
+
+import collections
+from PyQt5.QtCore import Qt, QTimer
+from typing import TYPE_CHECKING, Optional, Dict
+from cura.Machines.Models.IntentTranslations import intent_translations
+
+from cura.Machines.Models.IntentModel import IntentModel
+from cura.Settings.IntentManager import IntentManager
+from UM.Qt.ListModel import ListModel
+from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes.
+from PyQt5.QtCore import pyqtProperty, pyqtSignal
+import cura.CuraApplication
+if TYPE_CHECKING:
+ from UM.Settings.ContainerRegistry import ContainerInterface
+
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
+
+## Lists the intent categories that are available for the current printer
+# configuration.
+class IntentCategoryModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ IntentCategoryRole = Qt.UserRole + 2
+ WeightRole = Qt.UserRole + 3
+ QualitiesRole = Qt.UserRole + 4
+ DescriptionRole = Qt.UserRole + 5
+
+ modelUpdated = pyqtSignal()
+
+ _translations = collections.OrderedDict() # type: "collections.OrderedDict[str,Dict[str,Optional[str]]]"
+
+ # Translations to user-visible string. Ordered by weight.
+ # TODO: Create a solution for this name and weight to be used dynamically.
+ @classmethod
+ def _get_translations(cls):
+ if len(cls._translations) == 0:
+ cls._translations["default"] = {
+ "name": catalog.i18nc("@label", "Default")
+ }
+ cls._translations["visual"] = {
+ "name": catalog.i18nc("@label", "Visual"),
+ "description": catalog.i18nc("@text", "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality.")
+ }
+ cls._translations["engineering"] = {
+ "name": catalog.i18nc("@label", "Engineering"),
+ "description": catalog.i18nc("@text", "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances.")
+ }
+ cls._translations["quick"] = {
+ "name": catalog.i18nc("@label", "Draft"),
+ "description": catalog.i18nc("@text", "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction.")
+ }
+ return cls._translations
+
+ ## Creates a new model for a certain intent category.
+ # \param The category to list the intent profiles for.
+ def __init__(self, intent_category: str) -> None:
+ super().__init__()
+ self._intent_category = intent_category
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.IntentCategoryRole, "intent_category")
+ self.addRoleName(self.WeightRole, "weight")
+ self.addRoleName(self.QualitiesRole, "qualities")
+ self.addRoleName(self.DescriptionRole, "description")
+
+ application = cura.CuraApplication.CuraApplication.getInstance()
+
+ ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange)
+ ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange)
+ machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
+ machine_manager.activeMaterialChanged.connect(self.update)
+ machine_manager.activeVariantChanged.connect(self.update)
+ machine_manager.extruderChanged.connect(self.update)
+
+ extruder_manager = application.getExtruderManager()
+ extruder_manager.extrudersChanged.connect(self.update)
+
+ self._update_timer = QTimer()
+ self._update_timer.setInterval(500)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._update)
+
+ self.update()
+
+ ## Updates the list of intents if an intent profile was added or removed.
+ def _onContainerChange(self, container: "ContainerInterface") -> None:
+ if container.getMetaDataEntry("type") == "intent":
+ self.update()
+
+ def update(self):
+ self._update_timer.start()
+
+ ## Updates the list of intents.
+ def _update(self) -> None:
+ available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
+ result = []
+ for category in available_categories:
+ qualities = IntentModel()
+ qualities.setIntentCategory(category)
+ result.append({
+ "name": IntentCategoryModel.translation(category, "name", catalog.i18nc("@label", "Unknown")),
+ "description": IntentCategoryModel.translation(category, "description", None),
+ "intent_category": category,
+ "weight": list(IntentCategoryModel._get_translations().keys()).index(category),
+ "qualities": qualities
+ })
+ result.sort(key = lambda k: k["weight"])
+ self.setItems(result)
+
+ ## Get a display value for a category.
+ ## for categories and keys
+ @staticmethod
+ def translation(category: str, key: str, default: Optional[str] = None):
+ display_strings = IntentCategoryModel._get_translations().get(category, {})
+ return display_strings.get(key, default)
diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py
new file mode 100644
index 0000000000..986f28a826
--- /dev/null
+++ b/cura/Machines/Models/IntentModel.py
@@ -0,0 +1,135 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional, Dict, Any, Set, List
+
+from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal
+
+import cura.CuraApplication
+from UM.Qt.ListModel import ListModel
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Logger import Logger
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Machines.MaterialNode import MaterialNode
+from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
+from cura.Machines.QualityGroup import QualityGroup
+
+
+class IntentModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ QualityTypeRole = Qt.UserRole + 2
+ LayerHeightRole = Qt.UserRole + 3
+ AvailableRole = Qt.UserRole + 4
+ IntentRole = Qt.UserRole + 5
+
+ def __init__(self, parent: Optional[QObject] = None) -> None:
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.QualityTypeRole, "quality_type")
+ self.addRoleName(self.LayerHeightRole, "layer_height")
+ self.addRoleName(self.AvailableRole, "available")
+ self.addRoleName(self.IntentRole, "intent_category")
+
+ self._intent_category = "engineering"
+
+ machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
+ machine_manager.globalContainerChanged.connect(self._update)
+ machine_manager.extruderChanged.connect(self._update) # We also need to update if an extruder gets disabled
+ ContainerRegistry.getInstance().containerAdded.connect(self._onChanged)
+ ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged)
+ self._layer_height_unit = "" # This is cached
+ self._update()
+
+ intentCategoryChanged = pyqtSignal()
+
+ def setIntentCategory(self, new_category: str) -> None:
+ if self._intent_category != new_category:
+ self._intent_category = new_category
+ self.intentCategoryChanged.emit()
+ self._update()
+
+ @pyqtProperty(str, fset = setIntentCategory, notify = intentCategoryChanged)
+ def intentCategory(self) -> str:
+ return self._intent_category
+
+ def _onChanged(self, container):
+ if container.getMetaDataEntry("type") == "intent":
+ self._update()
+
+ def _update(self) -> None:
+ new_items = [] # type: List[Dict[str, Any]]
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack:
+ self.setItems(new_items)
+ return
+ quality_groups = ContainerTree.getInstance().getCurrentQualityGroups()
+
+ material_nodes = self._getActiveMaterials()
+
+ added_quality_type_set = set() # type: Set[str]
+ for material_node in material_nodes:
+ intents = self._getIntentsForMaterial(material_node, quality_groups)
+ for intent in intents:
+ if intent["quality_type"] not in added_quality_type_set:
+ new_items.append(intent)
+ added_quality_type_set.add(intent["quality_type"])
+
+ # Now that we added all intents that we found something for, ensure that we set add ticks (and layer_heights)
+ # for all groups that we don't have anything for (and set it to not available)
+ for quality_type, quality_group in quality_groups.items():
+ # Add the intents that are of the correct category
+ if quality_type not in added_quality_type_set:
+ layer_height = fetchLayerHeight(quality_group)
+ new_items.append({"name": "Unavailable",
+ "quality_type": quality_type,
+ "layer_height": layer_height,
+ "intent_category": self._intent_category,
+ "available": False})
+ added_quality_type_set.add(quality_type)
+
+ new_items = sorted(new_items, key = lambda x: x["layer_height"])
+ self.setItems(new_items)
+
+ ## Get the active materials for all extruders. No duplicates will be returned
+ def _getActiveMaterials(self) -> Set["MaterialNode"]:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return set()
+
+ container_tree = ContainerTree.getInstance()
+ machine_node = container_tree.machines[global_stack.definition.getId()]
+ nodes = set() # type: Set[MaterialNode]
+
+ for extruder in global_stack.extruderList:
+ active_variant_name = extruder.variant.getMetaDataEntry("name")
+ if active_variant_name not in machine_node.variants:
+ Logger.log("w", "Could not find the variant %s", active_variant_name)
+ continue
+ active_variant_node = machine_node.variants[active_variant_name]
+ active_material_node = active_variant_node.materials[extruder.material.getMetaDataEntry("base_file")]
+ nodes.add(active_material_node)
+
+ return nodes
+
+ def _getIntentsForMaterial(self, active_material_node: "MaterialNode", quality_groups: Dict[str, "QualityGroup"]) -> List[Dict[str, Any]]:
+ extruder_intents = [] # type: List[Dict[str, Any]]
+
+ for quality_id, quality_node in active_material_node.qualities.items():
+ if quality_node.quality_type not in quality_groups: # Don't add the empty quality type (or anything else that would crash, defensively).
+ continue
+ quality_group = quality_groups[quality_node.quality_type]
+ layer_height = fetchLayerHeight(quality_group)
+
+ for intent_id, intent_node in quality_node.intents.items():
+ if intent_node.intent_category != self._intent_category:
+ continue
+ extruder_intents.append({"name": quality_group.name,
+ "quality_type": quality_group.quality_type,
+ "layer_height": layer_height,
+ "available": quality_group.is_available,
+ "intent_category": self._intent_category
+ })
+ return extruder_intents
+
+ def __repr__(self):
+ return str(self.items)
diff --git a/cura/Machines/Models/IntentTranslations.py b/cura/Machines/Models/IntentTranslations.py
new file mode 100644
index 0000000000..050fb1de56
--- /dev/null
+++ b/cura/Machines/Models/IntentTranslations.py
@@ -0,0 +1,24 @@
+import collections
+from typing import Dict, Optional
+
+from UM.i18n import i18nCatalog
+from typing import Dict, Optional
+catalog = i18nCatalog("cura")
+
+
+intent_translations = collections.OrderedDict() # type: collections.OrderedDict[str, Dict[str, Optional[str]]]
+intent_translations["default"] = {
+ "name": catalog.i18nc("@label", "Default")
+}
+intent_translations["visual"] = {
+ "name": catalog.i18nc("@label", "Visual"),
+ "description": catalog.i18nc("@text", "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality.")
+}
+intent_translations["engineering"] = {
+ "name": catalog.i18nc("@label", "Engineering"),
+ "description": catalog.i18nc("@text", "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances.")
+}
+intent_translations["quick"] = {
+ "name": catalog.i18nc("@label", "Draft"),
+ "description": catalog.i18nc("@text", "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction.")
+}
diff --git a/cura/Machines/Models/MachineManagementModel.py b/cura/Machines/Models/MachineManagementModel.py
deleted file mode 100644
index 3297b8a467..0000000000
--- a/cura/Machines/Models/MachineManagementModel.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from UM.Qt.ListModel import ListModel
-
-from PyQt5.QtCore import Qt
-
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.ContainerStack import ContainerStack
-
-from UM.i18n import i18nCatalog
-catalog = i18nCatalog("cura")
-
-
-#
-# This the QML model for the quality management page.
-#
-class MachineManagementModel(ListModel):
- NameRole = Qt.UserRole + 1
- IdRole = Qt.UserRole + 2
- MetaDataRole = Qt.UserRole + 3
- GroupRole = Qt.UserRole + 4
-
- def __init__(self, parent = None):
- super().__init__(parent)
- self.addRoleName(self.NameRole, "name")
- self.addRoleName(self.IdRole, "id")
- self.addRoleName(self.MetaDataRole, "metadata")
- self.addRoleName(self.GroupRole, "group")
- self._local_container_stacks = []
- self._network_container_stacks = []
-
- # Listen to changes
- ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
- ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
- ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
- self._filter_dict = {}
- self._update()
-
- ## Handler for container added/removed events from registry
- def _onContainerChanged(self, container):
- # We only need to update when the added / removed container is a stack.
- if isinstance(container, ContainerStack) and container.getMetaDataEntry("type") == "machine":
- self._update()
-
- ## Private convenience function to reset & repopulate the model.
- def _update(self):
- items = []
-
- # Get first the network enabled printers
- network_filter_printers = {"type": "machine",
- "um_network_key": "*",
- "hidden": "False"}
- self._network_container_stacks = ContainerRegistry.getInstance().findContainerStacks(**network_filter_printers)
- self._network_container_stacks.sort(key = lambda i: i.getMetaDataEntry("group_name", ""))
-
- for container in self._network_container_stacks:
- metadata = container.getMetaData().copy()
- if container.getBottom():
- metadata["definition_name"] = container.getBottom().getName()
-
- items.append({"name": metadata.get("group_name", ""),
- "id": container.getId(),
- "metadata": metadata,
- "group": catalog.i18nc("@info:title", "Network enabled printers")})
-
- # Get now the local printers
- local_filter_printers = {"type": "machine", "um_network_key": None}
- self._local_container_stacks = ContainerRegistry.getInstance().findContainerStacks(**local_filter_printers)
- self._local_container_stacks.sort(key = lambda i: i.getName())
-
- for container in self._local_container_stacks:
- metadata = container.getMetaData().copy()
- if container.getBottom():
- metadata["definition_name"] = container.getBottom().getName()
-
- items.append({"name": container.getName(),
- "id": container.getId(),
- "metadata": metadata,
- "group": catalog.i18nc("@info:title", "Local printers")})
-
- self.setItems(items)
diff --git a/cura/Machines/Models/MachineModelUtils.py b/cura/Machines/Models/MachineModelUtils.py
new file mode 100644
index 0000000000..a23b1ff3a5
--- /dev/null
+++ b/cura/Machines/Models/MachineModelUtils.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import TYPE_CHECKING
+
+from UM.Settings.SettingFunction import SettingFunction
+
+if TYPE_CHECKING:
+ from cura.Machines.QualityGroup import QualityGroup
+
+layer_height_unit = ""
+
+
+def fetchLayerHeight(quality_group: "QualityGroup") -> float:
+ from cura.CuraApplication import CuraApplication
+ global_stack = CuraApplication.getInstance().getMachineManager().activeMachine
+
+ default_layer_height = global_stack.definition.getProperty("layer_height", "value")
+
+ # Get layer_height from the quality profile for the GlobalStack
+ if quality_group.node_for_global is None:
+ return float(default_layer_height)
+ container = quality_group.node_for_global.container
+
+ layer_height = default_layer_height
+ if container and container.hasProperty("layer_height", "value"):
+ layer_height = container.getProperty("layer_height", "value")
+ else:
+ # Look for layer_height in the GlobalStack from material -> definition
+ container = global_stack.definition
+ if container and container.hasProperty("layer_height", "value"):
+ layer_height = container.getProperty("layer_height", "value")
+
+ if isinstance(layer_height, SettingFunction):
+ layer_height = layer_height(global_stack)
+
+ return float(layer_height)
diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py
index ac82cf6670..184d27f390 100644
--- a/cura/Machines/Models/MaterialBrandsModel.py
+++ b/cura/Machines/Models/MaterialBrandsModel.py
@@ -1,9 +1,8 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
+from PyQt5.QtCore import Qt, pyqtSignal
from UM.Qt.ListModel import ListModel
-from UM.Logger import Logger
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
class MaterialTypesModel(ListModel):
@@ -30,8 +29,7 @@ class MaterialBrandsModel(BaseMaterialsModel):
def _update(self):
if not self._canUpdate():
return
- # Get updated list of favorites
- self._favorite_ids = self._material_manager.getFavorites()
+ super()._update()
brand_item_list = []
brand_group_dict = {}
@@ -56,7 +54,8 @@ class MaterialBrandsModel(BaseMaterialsModel):
# Now handle the individual materials
item = self._createMaterialItem(root_material_id, container_node)
- brand_group_dict[brand][material_type].append(item)
+ if item:
+ brand_group_dict[brand][material_type].append(item)
# Part 2: Organize the tree into models
#
diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py
new file mode 100644
index 0000000000..f00b81e987
--- /dev/null
+++ b/cura/Machines/Models/MaterialManagementModel.py
@@ -0,0 +1,246 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import copy # To duplicate materials.
+from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot # To allow the preference page proxy to be used from the actual preferences page.
+from typing import Any, Dict, Optional, TYPE_CHECKING
+import uuid # To generate new GUIDs for new materials.
+
+from UM.i18n import i18nCatalog
+from UM.Logger import Logger
+from UM.Signal import postponeSignals, CompressTechnique
+
+import cura.CuraApplication # Imported like this to prevent circular imports.
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To find the sets of materials belonging to each other, and currently loaded extruder stacks.
+
+if TYPE_CHECKING:
+ from cura.Machines.MaterialNode import MaterialNode
+
+catalog = i18nCatalog("cura")
+
+## Proxy class to the materials page in the preferences.
+#
+# This class handles the actions in that page, such as creating new materials,
+# renaming them, etc.
+class MaterialManagementModel(QObject):
+ ## Triggered when a favorite is added or removed.
+ # \param The base file of the material is provided as parameter when this
+ # emits.
+ favoritesChanged = pyqtSignal(str)
+
+ ## Can a certain material be deleted, or is it still in use in one of the
+ # container stacks anywhere?
+ #
+ # We forbid the user from deleting a material if it's in use in any stack.
+ # Deleting it while it's in use can lead to corrupted stacks. In the
+ # future we might enable this functionality again (deleting the material
+ # from those stacks) but for now it is easier to prevent the user from
+ # doing this.
+ # \param material_node The ContainerTree node of the material to check.
+ # \return Whether or not the material can be removed.
+ @pyqtSlot("QVariant", result = bool)
+ def canMaterialBeRemoved(self, material_node: "MaterialNode") -> bool:
+ container_registry = CuraContainerRegistry.getInstance()
+ ids_to_remove = {metadata.get("id", "") for metadata in container_registry.findInstanceContainersMetadata(base_file = material_node.base_file)}
+ for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"):
+ if extruder_stack.material.getId() in ids_to_remove:
+ return False
+ return True
+
+ ## Change the user-visible name of a material.
+ # \param material_node The ContainerTree node of the material to rename.
+ # \param name The new name for the material.
+ @pyqtSlot("QVariant", str)
+ def setMaterialName(self, material_node: "MaterialNode", name: str) -> None:
+ container_registry = CuraContainerRegistry.getInstance()
+ root_material_id = material_node.base_file
+ if container_registry.isReadOnly(root_material_id):
+ Logger.log("w", "Cannot set name of read-only container %s.", root_material_id)
+ return
+ return container_registry.findContainers(id = root_material_id)[0].setName(name)
+
+ ## Deletes a material from Cura.
+ #
+ # This function does not do any safety checking any more. Please call this
+ # function only if:
+ # - The material is not read-only.
+ # - The material is not used in any stacks.
+ # If the material was not lazy-loaded yet, this will fully load the
+ # container. When removing this material node, all other materials with
+ # the same base fill will also be removed.
+ # \param material_node The material to remove.
+ @pyqtSlot("QVariant")
+ def removeMaterial(self, material_node: "MaterialNode") -> None:
+ container_registry = CuraContainerRegistry.getInstance()
+ materials_this_base_file = container_registry.findContainersMetadata(base_file = material_node.base_file)
+
+ # The material containers belonging to the same material file are supposed to work together. This postponeSignals()
+ # does two things:
+ # - optimizing the signal emitting.
+ # - making sure that the signals will only be emitted after all the material containers have been removed.
+ with postponeSignals(container_registry.containerRemoved, compress = CompressTechnique.CompressPerParameterValue):
+ # CURA-6886: Some containers may not have been loaded. If remove one material container, its material file
+ # will be removed. If later we remove a sub-material container which hasn't been loaded previously, it will
+ # crash because removeContainer() requires to load the container first, but the material file was already
+ # gone.
+ for material_metadata in materials_this_base_file:
+ container_registry.findInstanceContainers(id = material_metadata["id"])
+ for material_metadata in materials_this_base_file:
+ container_registry.removeContainer(material_metadata["id"])
+
+ ## Creates a duplicate of a material with the same GUID and base_file
+ # metadata.
+ # \param base_file: The base file of the material to duplicate.
+ # \param new_base_id A new material ID for the base material. The IDs of
+ # the submaterials will be based off this one. If not provided, a material
+ # ID will be generated automatically.
+ # \param new_metadata Metadata for the new material. If not provided, this
+ # will be duplicated from the original material.
+ # \return The root material ID of the duplicate material.
+ def duplicateMaterialByBaseFile(self, base_file: str, new_base_id: Optional[str] = None,
+ new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]:
+ container_registry = CuraContainerRegistry.getInstance()
+
+ root_materials = container_registry.findContainers(id = base_file)
+ if not root_materials:
+ Logger.log("i", "Unable to duplicate the root material with ID {root_id}, because it doesn't exist.".format(root_id = base_file))
+ return None
+ root_material = root_materials[0]
+
+ # Ensure that all settings are saved.
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ application.saveSettings()
+
+ # Create a new ID and container to hold the data.
+ if new_base_id is None:
+ new_base_id = container_registry.uniqueName(root_material.getId())
+ new_root_material = copy.deepcopy(root_material)
+ new_root_material.getMetaData()["id"] = new_base_id
+ new_root_material.getMetaData()["base_file"] = new_base_id
+ if new_metadata is not None:
+ new_root_material.getMetaData().update(new_metadata)
+ new_containers = [new_root_material]
+
+ # Clone all submaterials.
+ for container_to_copy in container_registry.findInstanceContainers(base_file = base_file):
+ if container_to_copy.getId() == base_file:
+ continue # We already have that one. Skip it.
+ new_id = new_base_id
+ definition = container_to_copy.getMetaDataEntry("definition")
+ if definition != "fdmprinter":
+ new_id += "_" + definition
+ variant_name = container_to_copy.getMetaDataEntry("variant_name")
+ if variant_name:
+ new_id += "_" + variant_name.replace(" ", "_")
+
+ new_container = copy.deepcopy(container_to_copy)
+ new_container.getMetaData()["id"] = new_id
+ new_container.getMetaData()["base_file"] = new_base_id
+ if new_metadata is not None:
+ new_container.getMetaData().update(new_metadata)
+ new_containers.append(new_container)
+
+ # CURA-6863: Nodes in ContainerTree will be updated upon ContainerAdded signals, one at a time. It will use the
+ # best fit material container at the time it sees one. For example, if you duplicate and get generic_pva #2,
+ # if the node update function sees the containers in the following order:
+ #
+ # - generic_pva #2
+ # - generic_pva #2_um3_aa04
+ #
+ # It will first use "generic_pva #2" because that's the best fit it has ever seen, and later "generic_pva #2_um3_aa04"
+ # once it sees that. Because things run in the Qt event loop, they don't happen at the same time. This means if
+ # between those two events, the ContainerTree will have nodes that contain invalid data.
+ #
+ # This sort fixes the problem by emitting the most specific containers first.
+ new_containers = sorted(new_containers, key = lambda x: x.getId(), reverse = True)
+
+ # Optimization. Serving the same purpose as the postponeSignals() in removeMaterial()
+ # postpone the signals emitted when duplicating materials. This is easier on the event loop; changes the
+ # behavior to be like a transaction. Prevents concurrency issues.
+ with postponeSignals(container_registry.containerAdded, compress=CompressTechnique.CompressPerParameterValue):
+ for container_to_add in new_containers:
+ container_to_add.setDirty(True)
+ container_registry.addContainer(container_to_add)
+
+ # If the duplicated material was favorite then the new material should also be added to the favorites.
+ favorites_set = set(application.getPreferences().getValue("cura/favorite_materials").split(";"))
+ if base_file in favorites_set:
+ favorites_set.add(new_base_id)
+ application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set))
+
+ return new_base_id
+
+ ## Creates a duplicate of a material with the same GUID and base_file
+ # metadata.
+ # \param material_node The node representing the material to duplicate.
+ # \param new_base_id A new material ID for the base material. The IDs of
+ # the submaterials will be based off this one. If not provided, a material
+ # ID will be generated automatically.
+ # \param new_metadata Metadata for the new material. If not provided, this
+ # will be duplicated from the original material.
+ # \return The root material ID of the duplicate material.
+ @pyqtSlot("QVariant", result = str)
+ def duplicateMaterial(self, material_node: "MaterialNode", new_base_id: Optional[str] = None,
+ new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]:
+ return self.duplicateMaterialByBaseFile(material_node.base_file, new_base_id, new_metadata)
+
+ ## Create a new material by cloning the preferred material for the current
+ # material diameter and generate a new GUID.
+ #
+ # The material type is explicitly left to be the one from the preferred
+ # material, since this allows the user to still have SOME profiles to work
+ # with.
+ # \return The ID of the newly created material.
+ @pyqtSlot(result = str)
+ def createMaterial(self) -> str:
+ # Ensure all settings are saved.
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ application.saveSettings()
+
+ # Find the preferred material.
+ extruder_stack = application.getMachineManager().activeStack
+ active_variant_name = extruder_stack.variant.getName()
+ approximate_diameter = int(extruder_stack.approximateMaterialDiameter)
+ global_container_stack = application.getGlobalContainerStack()
+ if not global_container_stack:
+ return ""
+ machine_node = ContainerTree.getInstance().machines[global_container_stack.definition.getId()]
+ preferred_material_node = machine_node.variants[active_variant_name].preferredMaterial(approximate_diameter)
+
+ # Create a new ID & new metadata for the new material.
+ new_id = CuraContainerRegistry.getInstance().uniqueName("custom_material")
+ new_metadata = {"name": catalog.i18nc("@label", "Custom Material"),
+ "brand": catalog.i18nc("@label", "Custom"),
+ "GUID": str(uuid.uuid4()),
+ }
+
+ self.duplicateMaterial(preferred_material_node, new_base_id = new_id, new_metadata = new_metadata)
+ return new_id
+
+ ## Adds a certain material to the favorite materials.
+ # \param material_base_file The base file of the material to add.
+ @pyqtSlot(str)
+ def addFavorite(self, material_base_file: str) -> None:
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ favorites = application.getPreferences().getValue("cura/favorite_materials").split(";")
+ if material_base_file not in favorites:
+ favorites.append(material_base_file)
+ application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites))
+ application.saveSettings()
+ self.favoritesChanged.emit(material_base_file)
+
+ ## Removes a certain material from the favorite materials.
+ #
+ # If the material was not in the favorite materials, nothing happens.
+ @pyqtSlot(str)
+ def removeFavorite(self, material_base_file: str) -> None:
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ favorites = application.getPreferences().getValue("cura/favorite_materials").split(";")
+ try:
+ favorites.remove(material_base_file)
+ application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites))
+ application.saveSettings()
+ self.favoritesChanged.emit(material_base_file)
+ except ValueError: # Material was not in the favorites list.
+ Logger.log("w", "Material {material_base_file} was already not a favorite material.".format(material_base_file = material_base_file))
diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py
index 785ff5b9b9..5f7f8b02f5 100644
--- a/cura/Machines/Models/NozzleModel.py
+++ b/cura/Machines/Models/NozzleModel.py
@@ -1,14 +1,12 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt
-from UM.Application import Application
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
-from UM.Util import parseBool
-
-from cura.Machines.VariantType import VariantType
+import cura.CuraApplication # Imported like this to prevent circular dependencies.
+from cura.Machines.ContainerTree import ContainerTree
class NozzleModel(ListModel):
@@ -23,33 +21,24 @@ class NozzleModel(ListModel):
self.addRoleName(self.HotendNameRole, "hotend_name")
self.addRoleName(self.ContainerNodeRole, "container_node")
- self._application = Application.getInstance()
- self._machine_manager = self._application.getMachineManager()
- self._variant_manager = self._application.getVariantManager()
-
- self._machine_manager.globalContainerChanged.connect(self._update)
+ cura.CuraApplication.CuraApplication.getInstance().getMachineManager().globalContainerChanged.connect(self._update)
self._update()
def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
- global_stack = self._machine_manager.activeMachine
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
if global_stack is None:
self.setItems([])
return
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
- has_variants = parseBool(global_stack.getMetaDataEntry("has_variants", False))
- if not has_variants:
- self.setItems([])
- return
-
- variant_node_dict = self._variant_manager.getVariantNodes(global_stack, VariantType.NOZZLE)
- if not variant_node_dict:
+ if not machine_node.has_variants:
self.setItems([])
return
item_list = []
- for hotend_name, container_node in sorted(variant_node_dict.items(), key = lambda i: i[0].upper()):
+ for hotend_name, container_node in sorted(machine_node.variants.items(), key = lambda i: i[0].upper()):
item = {"id": hotend_name,
"hotend_name": hotend_name,
"container_node": container_node
@@ -57,4 +46,4 @@ class NozzleModel(ListModel):
item_list.append(item)
- self.setItems(item_list)
+ self.setItems(item_list)
\ No newline at end of file
diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py
index 315ab010bb..74dc8649d0 100644
--- a/cura/Machines/Models/QualityManagementModel.py
+++ b/cura/Machines/Models/QualityManagementModel.py
@@ -1,10 +1,30 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import Qt, pyqtSlot
+from typing import Any, cast, Dict, Optional, TYPE_CHECKING
+from PyQt5.QtCore import pyqtSlot, QObject, Qt, QTimer
-from UM.Qt.ListModel import ListModel
from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+from UM.Settings.InstanceContainer import InstanceContainer # To create new profiles.
+
+import cura.CuraApplication # Imported this way to prevent circular imports.
+from cura.Settings.ContainerManager import ContainerManager
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container
+from cura.Settings.IntentManager import IntentManager
+from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
+from cura.Machines.Models.IntentTranslations import intent_translations
+
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
+if TYPE_CHECKING:
+ from UM.Settings.Interfaces import ContainerInterface
+ from cura.Machines.QualityChangesGroup import QualityChangesGroup
+ from cura.Settings.ExtruderStack import ExtruderStack
+ from cura.Settings.GlobalStack import GlobalStack
+
#
# This the QML model for the quality management page.
@@ -13,26 +33,257 @@ class QualityManagementModel(ListModel):
NameRole = Qt.UserRole + 1
IsReadOnlyRole = Qt.UserRole + 2
QualityGroupRole = Qt.UserRole + 3
- QualityChangesGroupRole = Qt.UserRole + 4
+ QualityTypeRole = Qt.UserRole + 4
+ QualityChangesGroupRole = Qt.UserRole + 5
+ IntentCategoryRole = Qt.UserRole + 6
+ SectionNameRole = Qt.UserRole + 7
- def __init__(self, parent = None):
+ def __init__(self, parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.IsReadOnlyRole, "is_read_only")
self.addRoleName(self.QualityGroupRole, "quality_group")
+ self.addRoleName(self.QualityTypeRole, "quality_type")
self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group")
+ self.addRoleName(self.IntentCategoryRole, "intent_category")
+ self.addRoleName(self.SectionNameRole, "section_name")
- from cura.CuraApplication import CuraApplication
- self._container_registry = CuraApplication.getInstance().getContainerRegistry()
- self._machine_manager = CuraApplication.getInstance().getMachineManager()
- self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
- self._quality_manager = CuraApplication.getInstance().getQualityManager()
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ container_registry = application.getContainerRegistry()
+ self._machine_manager = application.getMachineManager()
+ self._machine_manager.activeQualityGroupChanged.connect(self._onChange)
+ self._machine_manager.activeStackChanged.connect(self._onChange)
+ self._machine_manager.extruderChanged.connect(self._onChange)
+ self._machine_manager.globalContainerChanged.connect(self._onChange)
- self._machine_manager.globalContainerChanged.connect(self._update)
- self._quality_manager.qualitiesUpdated.connect(self._update)
+ self._extruder_manager = application.getExtruderManager()
+ self._extruder_manager.extrudersChanged.connect(self._onChange)
- self._update()
+ container_registry.containerAdded.connect(self._qualityChangesListChanged)
+ container_registry.containerRemoved.connect(self._qualityChangesListChanged)
+ container_registry.containerMetaDataChanged.connect(self._qualityChangesListChanged)
+
+ self._update_timer = QTimer()
+ self._update_timer.setInterval(100)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._update)
+
+ self._onChange()
+
+ def _onChange(self) -> None:
+ self._update_timer.start()
+
+ ## Deletes a custom profile. It will be gone forever.
+ # \param quality_changes_group The quality changes group representing the
+ # profile to delete.
+ @pyqtSlot(QObject)
+ def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None:
+ Logger.log("i", "Removing quality changes group {group_name}".format(group_name = quality_changes_group.name))
+ removed_quality_changes_ids = set()
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ for metadata in [quality_changes_group.metadata_for_global] + list(quality_changes_group.metadata_per_extruder.values()):
+ container_id = metadata["id"]
+ container_registry.removeContainer(container_id)
+ removed_quality_changes_ids.add(container_id)
+
+ # Reset all machines that have activated this custom profile.
+ for global_stack in container_registry.findContainerStacks(type = "machine"):
+ if global_stack.qualityChanges.getId() in removed_quality_changes_ids:
+ global_stack.qualityChanges = empty_quality_changes_container
+ for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"):
+ if extruder_stack.qualityChanges.getId() in removed_quality_changes_ids:
+ extruder_stack.qualityChanges = empty_quality_changes_container
+
+ ## Rename a custom profile.
+ #
+ # Because the names must be unique, the new name may not actually become
+ # the name that was given. The actual name is returned by this function.
+ # \param quality_changes_group The custom profile that must be renamed.
+ # \param new_name The desired name for the profile.
+ # \return The actual new name of the profile, after making the name
+ # unique.
+ @pyqtSlot(QObject, str, result = str)
+ def renameQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", new_name: str) -> str:
+ Logger.log("i", "Renaming QualityChangesGroup {old_name} to {new_name}.".format(old_name = quality_changes_group.name, new_name = new_name))
+ if new_name == quality_changes_group.name:
+ Logger.log("i", "QualityChangesGroup name {name} unchanged.".format(name = quality_changes_group.name))
+ return new_name
+
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ container_registry = application.getContainerRegistry()
+ new_name = container_registry.uniqueName(new_name)
+ # CURA-6842
+ # FIXME: setName() will trigger metaDataChanged signal that are connected with type Qt.AutoConnection. In this
+ # case, setName() will trigger direct connections which in turn causes the quality changes group and the models
+ # to update. Because multiple containers need to be renamed, and every time a container gets renamed, updates
+ # gets triggered and this results in partial updates. For example, if we rename the global quality changes
+ # container first, the rest of the system still thinks that I have selected "my_profile" instead of
+ # "my_new_profile", but an update already gets triggered, and the quality changes group that's selected will
+ # have no container for the global stack, because "my_profile" just got renamed to "my_new_profile". This results
+ # in crashes because the rest of the system assumes that all data in a QualityChangesGroup will be correct.
+ #
+ # Renaming the container for the global stack in the end seems to be ok, because the assumption is mostly based
+ # on the quality changes container for the global stack.
+ for metadata in quality_changes_group.metadata_per_extruder.values():
+ extruder_container = cast(InstanceContainer, container_registry.findContainers(id = metadata["id"])[0])
+ extruder_container.setName(new_name)
+ global_container = cast(InstanceContainer, container_registry.findContainers(id=quality_changes_group.metadata_for_global["id"])[0])
+ global_container.setName(new_name)
+
+ quality_changes_group.name = new_name
+
+ application.getMachineManager().activeQualityChanged.emit()
+ application.getMachineManager().activeQualityGroupChanged.emit()
+
+ return new_name
+
+ ## Duplicates a given quality profile OR quality changes profile.
+ # \param new_name The desired name of the new profile. This will be made
+ # unique, so it might end up with a different name.
+ # \param quality_model_item The item of this model to duplicate, as
+ # dictionary. See the descriptions of the roles of this list model.
+ @pyqtSlot(str, "QVariantMap")
+ def duplicateQualityChanges(self, new_name: str, quality_model_item: Dict[str, Any]) -> None:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack:
+ Logger.log("i", "No active global stack, cannot duplicate quality (changes) profile.")
+ return
+
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ new_name = container_registry.uniqueName(new_name)
+
+ intent_category = quality_model_item["intent_category"]
+ quality_group = quality_model_item["quality_group"]
+ quality_changes_group = quality_model_item["quality_changes_group"]
+ if quality_changes_group is None:
+ # Create global quality changes only.
+ new_quality_changes = self._createQualityChanges(quality_group.quality_type, intent_category, new_name,
+ global_stack, extruder_stack = None)
+ container_registry.addContainer(new_quality_changes)
+ else:
+ for metadata in [quality_changes_group.metadata_for_global] + list(quality_changes_group.metadata_per_extruder.values()):
+ containers = container_registry.findContainers(id = metadata["id"])
+ if not containers:
+ continue
+ container = containers[0]
+ new_id = container_registry.uniqueName(container.getId())
+ container_registry.addContainer(container.duplicate(new_id, new_name))
+
+ ## Create quality changes containers from the user containers in the active
+ # stacks.
+ #
+ # This will go through the global and extruder stacks and create
+ # quality_changes containers from the user containers in each stack. These
+ # then replace the quality_changes containers in the stack and clear the
+ # user settings.
+ # \param base_name The new name for the quality changes profile. The final
+ # name of the profile might be different from this, because it needs to be
+ # made unique.
+ @pyqtSlot(str)
+ def createQualityChanges(self, base_name: str) -> None:
+ machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
+
+ global_stack = machine_manager.activeMachine
+ if not global_stack:
+ return
+
+ active_quality_name = machine_manager.activeQualityOrQualityChangesName
+ if active_quality_name == "":
+ Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId())
+ return
+
+ machine_manager.blurSettings.emit()
+ if base_name is None or base_name == "":
+ base_name = active_quality_name
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ unique_name = container_registry.uniqueName(base_name)
+
+ # Go through the active stacks and create quality_changes containers from the user containers.
+ container_manager = ContainerManager.getInstance()
+ stack_list = [global_stack] + list(global_stack.extruders.values())
+ for stack in stack_list:
+ quality_container = stack.quality
+ quality_changes_container = stack.qualityChanges
+ if not quality_container or not quality_changes_container:
+ Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId())
+ continue
+
+ extruder_stack = None
+ intent_category = None
+ if stack.getMetaDataEntry("position") is not None:
+ extruder_stack = stack
+ intent_category = stack.intent.getMetaDataEntry("intent_category")
+ new_changes = self._createQualityChanges(quality_container.getMetaDataEntry("quality_type"), intent_category, unique_name, global_stack, extruder_stack)
+ container_manager._performMerge(new_changes, quality_changes_container, clear_settings = False)
+ container_manager._performMerge(new_changes, stack.userChanges)
+
+ container_registry.addContainer(new_changes)
+
+ ## Create a quality changes container with the given set-up.
+ # \param quality_type The quality type of the new container.
+ # \param intent_category The intent category of the new container.
+ # \param new_name The name of the container. This name must be unique.
+ # \param machine The global stack to create the profile for.
+ # \param extruder_stack The extruder stack to create the profile for. If
+ # not provided, only a global container will be created.
+ def _createQualityChanges(self, quality_type: str, intent_category: Optional[str], new_name: str, machine: "GlobalStack", extruder_stack: Optional["ExtruderStack"]) -> "InstanceContainer":
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ base_id = machine.definition.getId() if extruder_stack is None else extruder_stack.getId()
+ new_id = base_id + "_" + new_name
+ new_id = new_id.lower().replace(" ", "_")
+ new_id = container_registry.uniqueName(new_id)
+
+ # Create a new quality_changes container for the quality.
+ quality_changes = InstanceContainer(new_id)
+ quality_changes.setName(new_name)
+ quality_changes.setMetaDataEntry("type", "quality_changes")
+ quality_changes.setMetaDataEntry("quality_type", quality_type)
+ if intent_category is not None:
+ quality_changes.setMetaDataEntry("intent_category", intent_category)
+
+ # If we are creating a container for an extruder, ensure we add that to the container.
+ if extruder_stack is not None:
+ quality_changes.setMetaDataEntry("position", extruder_stack.getMetaDataEntry("position"))
+
+ # If the machine specifies qualities should be filtered, ensure we match the current criteria.
+ machine_definition_id = ContainerTree.getInstance().machines[machine.definition.getId()].quality_definition
+ quality_changes.setDefinition(machine_definition_id)
+
+ quality_changes.setMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.getInstance().SettingVersion)
+ return quality_changes
+
+ ## Triggered when any container changed.
+ #
+ # This filters the updates to the container manager: When it applies to
+ # the list of quality changes, we need to update our list.
+ def _qualityChangesListChanged(self, container: "ContainerInterface") -> None:
+ if container.getMetaDataEntry("type") == "quality_changes":
+ self._update()
+
+ @pyqtSlot("QVariantMap", result = str)
+ def getQualityItemDisplayName(self, quality_model_item: Dict[str, Any]) -> str:
+ quality_group = quality_model_item["quality_group"]
+ is_read_only = quality_model_item["is_read_only"]
+ intent_category = quality_model_item["intent_category"]
+
+ quality_level_name = "Not Supported"
+ if quality_group is not None:
+ quality_level_name = quality_group.name
+
+ display_name = quality_level_name
+
+ if intent_category != "default":
+ intent_display_name = catalog.i18nc("@label", intent_category.capitalize())
+ display_name = "{intent_name} - {the_rest}".format(intent_name = intent_display_name,
+ the_rest = display_name)
+
+ # A custom quality
+ if not is_read_only:
+ display_name = "{custom_profile_name} - {the_rest}".format(custom_profile_name = quality_model_item["name"],
+ the_rest = display_name)
+
+ return display_name
def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
@@ -42,38 +293,71 @@ class QualityManagementModel(ListModel):
self.setItems([])
return
- quality_group_dict = self._quality_manager.getQualityGroups(global_stack)
- quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(global_stack)
+ container_tree = ContainerTree.getInstance()
+ quality_group_dict = container_tree.getCurrentQualityGroups()
+ quality_changes_group_list = container_tree.getCurrentQualityChangesGroups()
available_quality_types = set(quality_type for quality_type, quality_group in quality_group_dict.items()
if quality_group.is_available)
- if not available_quality_types and not quality_changes_group_dict:
+ if not available_quality_types and not quality_changes_group_list:
# Nothing to show
self.setItems([])
return
item_list = []
- # Create quality group items
+ # Create quality group items (intent category = "default")
for quality_group in quality_group_dict.values():
if not quality_group.is_available:
continue
+ layer_height = fetchLayerHeight(quality_group)
+
item = {"name": quality_group.name,
"is_read_only": True,
"quality_group": quality_group,
- "quality_changes_group": None}
+ "quality_type": quality_group.quality_type,
+ "quality_changes_group": None,
+ "intent_category": "default",
+ "section_name": catalog.i18nc("@label", "Default"),
+ "layer_height": layer_height, # layer_height is only used for sorting
+ }
item_list.append(item)
- # Sort by quality names
- item_list = sorted(item_list, key = lambda x: x["name"].upper())
+ # Sort by layer_height for built-in qualities
+ item_list = sorted(item_list, key = lambda x: x["layer_height"])
+
+ # Create intent items (non-default)
+ available_intent_list = IntentManager.getInstance().getCurrentAvailableIntents()
+ available_intent_list = [i for i in available_intent_list if i[0] != "default"]
+ result = []
+ for intent_category, quality_type in available_intent_list:
+ result.append({
+ "name": quality_group_dict[quality_type].name, # Use the quality name as the display name
+ "is_read_only": True,
+ "quality_group": quality_group_dict[quality_type],
+ "quality_type": quality_type,
+ "quality_changes_group": None,
+ "intent_category": intent_category,
+ "section_name": catalog.i18nc("@label", intent_translations.get(intent_category, {}).get("name", catalog.i18nc("@label", "Unknown"))),
+ })
+ # Sort by quality_type for each intent category
+
+ result = sorted(result, key = lambda x: (list(intent_translations).index(x["intent_category"]), x["quality_type"]))
+ item_list += result
# Create quality_changes group items
quality_changes_item_list = []
- for quality_changes_group in quality_changes_group_dict.values():
+ for quality_changes_group in quality_changes_group_list:
+ # CURA-6913 Note that custom qualities can be based on "not supported", so the quality group can be None.
quality_group = quality_group_dict.get(quality_changes_group.quality_type)
+ quality_type = quality_changes_group.quality_type
item = {"name": quality_changes_group.name,
"is_read_only": False,
"quality_group": quality_group,
- "quality_changes_group": quality_changes_group}
+ "quality_type": quality_type,
+ "quality_changes_group": quality_changes_group,
+ "intent_category": quality_changes_group.intent_category,
+ "section_name": catalog.i18nc("@label", "Custom profiles"),
+ }
quality_changes_item_list.append(item)
# Sort quality_changes items by names and append to the item list
diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
index deabb6e9ba..3a79ceeaf1 100644
--- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
+++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
@@ -1,14 +1,13 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, QTimer
-from UM.Application import Application
+import cura.CuraApplication # Imported this way to prevent circular dependencies.
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
-from UM.Settings.SettingFunction import SettingFunction
-
-from cura.Machines.QualityManager import QualityGroup
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
#
@@ -36,14 +35,17 @@ class QualityProfilesDropDownMenuModel(ListModel):
self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group")
self.addRoleName(self.IsExperimentalRole, "is_experimental")
- self._application = Application.getInstance()
- self._machine_manager = self._application.getMachineManager()
- self._quality_manager = Application.getInstance().getQualityManager()
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ machine_manager = application.getMachineManager()
- self._application.globalContainerStackChanged.connect(self._onChange)
- self._machine_manager.activeQualityGroupChanged.connect(self._onChange)
- self._machine_manager.extruderChanged.connect(self._onChange)
- self._quality_manager.qualitiesUpdated.connect(self._onChange)
+ application.globalContainerStackChanged.connect(self._onChange)
+ machine_manager.activeQualityGroupChanged.connect(self._onChange)
+ machine_manager.activeMaterialChanged.connect(self._onChange)
+ machine_manager.activeVariantChanged.connect(self._onChange)
+ machine_manager.extruderChanged.connect(self._onChange)
+
+ extruder_manager = application.getExtruderManager()
+ extruder_manager.extrudersChanged.connect(self._onChange)
self._layer_height_unit = "" # This is cached
@@ -60,25 +62,36 @@ class QualityProfilesDropDownMenuModel(ListModel):
def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
- global_stack = self._machine_manager.activeMachine
+ # CURA-6836
+ # LabelBar is a repeater that creates labels for quality layer heights. Because of an optimization in
+ # UM.ListModel, the model will not remove all items and recreate new ones every time there's an update.
+ # Because LabelBar uses Repeater with Labels anchoring to "undefined" in certain cases, the anchoring will be
+ # kept the same as before.
+ self.setItems([])
+
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
if global_stack is None:
self.setItems([])
Logger.log("d", "No active GlobalStack, set quality profile model as empty.")
return
+ if not self._layer_height_unit:
+ unit = global_stack.definition.getProperty("layer_height", "unit")
+ if not unit:
+ unit = ""
+ self._layer_height_unit = unit
+
# Check for material compatibility
- if not self._machine_manager.activeMaterialsCompatible():
+ if not cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeMaterialsCompatible():
Logger.log("d", "No active material compatibility, set quality profile model as empty.")
self.setItems([])
return
- quality_group_dict = self._quality_manager.getQualityGroups(global_stack)
+ quality_group_dict = ContainerTree.getInstance().getCurrentQualityGroups()
item_list = []
- for key in sorted(quality_group_dict):
- quality_group = quality_group_dict[key]
-
- layer_height = self._fetchLayerHeight(quality_group)
+ for quality_group in quality_group_dict.values():
+ layer_height = fetchLayerHeight(quality_group)
item = {"name": quality_group.name,
"quality_type": quality_group.quality_type,
@@ -94,32 +107,3 @@ class QualityProfilesDropDownMenuModel(ListModel):
item_list = sorted(item_list, key = lambda x: x["layer_height"])
self.setItems(item_list)
-
- def _fetchLayerHeight(self, quality_group: "QualityGroup") -> float:
- global_stack = self._machine_manager.activeMachine
- if not self._layer_height_unit:
- unit = global_stack.definition.getProperty("layer_height", "unit")
- if not unit:
- unit = ""
- self._layer_height_unit = unit
-
- default_layer_height = global_stack.definition.getProperty("layer_height", "value")
-
- # Get layer_height from the quality profile for the GlobalStack
- if quality_group.node_for_global is None:
- return float(default_layer_height)
- container = quality_group.node_for_global.getContainer()
-
- layer_height = default_layer_height
- if container and container.hasProperty("layer_height", "value"):
- layer_height = container.getProperty("layer_height", "value")
- else:
- # Look for layer_height in the GlobalStack from material -> definition
- container = global_stack.definition
- if container and container.hasProperty("layer_height", "value"):
- layer_height = container.getProperty("layer_height", "value")
-
- if isinstance(layer_height, SettingFunction):
- layer_height = layer_height(global_stack)
-
- return float(layer_height)
diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py
index 88005e69ca..6835ffb68f 100644
--- a/cura/Machines/Models/QualitySettingsModel.py
+++ b/cura/Machines/Models/QualitySettingsModel.py
@@ -1,9 +1,9 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
-from UM.Application import Application
+import cura.CuraApplication
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
from UM.Settings.ContainerRegistry import ContainerRegistry
@@ -35,15 +35,13 @@ class QualitySettingsModel(ListModel):
self.addRoleName(self.CategoryRole, "category")
self._container_registry = ContainerRegistry.getInstance()
- self._application = Application.getInstance()
- self._quality_manager = self._application.getQualityManager()
+ self._application = cura.CuraApplication.CuraApplication.getInstance()
+ self._application.getMachineManager().activeStackChanged.connect(self._update)
self._selected_position = self.GLOBAL_STACK_POSITION #Must be either GLOBAL_STACK_POSITION or an extruder position (0, 1, etc.)
self._selected_quality_item = None # The selected quality in the quality management page
self._i18n_catalog = None
- self._quality_manager.qualitiesUpdated.connect(self._update)
-
self._update()
selectedPositionChanged = pyqtSignal()
@@ -93,21 +91,33 @@ class QualitySettingsModel(ListModel):
quality_node = quality_group.nodes_for_extruders.get(str(self._selected_position))
settings_keys = quality_group.getAllKeys()
quality_containers = []
- if quality_node is not None and quality_node.getContainer() is not None:
- quality_containers.append(quality_node.getContainer())
+ if quality_node is not None and quality_node.container is not None:
+ quality_containers.append(quality_node.container)
# Here, if the user has selected a quality changes, then "quality_changes_group" will not be None, and we fetch
# the settings in that quality_changes_group.
if quality_changes_group is not None:
- if self._selected_position == self.GLOBAL_STACK_POSITION:
- quality_changes_node = quality_changes_group.node_for_global
+ container_registry = ContainerRegistry.getInstance()
+ global_containers = container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])
+ global_container = None if len(global_containers) == 0 else global_containers[0]
+ extruders_containers = {pos: container_registry.findContainers(id = quality_changes_group.metadata_per_extruder[pos]["id"]) for pos in quality_changes_group.metadata_per_extruder}
+ extruders_container = {pos: None if not containers else containers[0] for pos, containers in extruders_containers.items()}
+ if self._selected_position == self.GLOBAL_STACK_POSITION and global_container:
+ quality_changes_metadata = global_container.getMetaData()
else:
- quality_changes_node = quality_changes_group.nodes_for_extruders.get(str(self._selected_position))
- if quality_changes_node is not None and quality_changes_node.getContainer() is not None: # it can be None if number of extruders are changed during runtime
- quality_containers.insert(0, quality_changes_node.getContainer())
- settings_keys.update(quality_changes_group.getAllKeys())
+ quality_changes_metadata = extruders_container.get(str(self._selected_position))
+ if quality_changes_metadata is not None: # It can be None if number of extruders are changed during runtime.
+ container = container_registry.findContainers(id = quality_changes_metadata["id"])
+ if container:
+ quality_containers.insert(0, container[0])
- # We iterate over all definitions instead of settings in a quality/qualtiy_changes group is because in the GUI,
+ if global_container:
+ settings_keys.update(global_container.getAllKeys())
+ for container in extruders_container.values():
+ if container:
+ settings_keys.update(container.getAllKeys())
+
+ # We iterate over all definitions instead of settings in a quality/quality_changes group is because in the GUI,
# the settings are grouped together by categories, and we had to go over all the definitions to figure out
# which setting belongs in which category.
current_category = ""
diff --git a/cura/Settings/UserChangesModel.py b/cura/Machines/Models/UserChangesModel.py
similarity index 98%
rename from cura/Settings/UserChangesModel.py
rename to cura/Machines/Models/UserChangesModel.py
index 9a26e5607e..ec623f0f38 100644
--- a/cura/Settings/UserChangesModel.py
+++ b/cura/Machines/Models/UserChangesModel.py
@@ -10,7 +10,6 @@ from UM.Application import Application
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Settings.SettingFunction import SettingFunction
-
from UM.Qt.ListModel import ListModel
@@ -51,7 +50,7 @@ class UserChangesModel(ListModel):
return
stacks = [global_stack]
- stacks.extend(global_stack.extruders.values())
+ stacks.extend(global_stack.extruderList)
# Check if the definition container has a translation file and ensure it's loaded.
definition = global_stack.getBottom()
diff --git a/cura/Machines/QualityChangesGroup.py b/cura/Machines/QualityChangesGroup.py
index 7844b935dc..655060070b 100644
--- a/cura/Machines/QualityChangesGroup.py
+++ b/cura/Machines/QualityChangesGroup.py
@@ -1,33 +1,37 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import TYPE_CHECKING
+from typing import Any, Dict, Optional
-from UM.Application import Application
-from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
-
-from .QualityGroup import QualityGroup
-
-if TYPE_CHECKING:
- from cura.Machines.QualityNode import QualityNode
+from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
-class QualityChangesGroup(QualityGroup):
- def __init__(self, name: str, quality_type: str, parent = None) -> None:
- super().__init__(name, quality_type, parent)
- self._container_registry = Application.getInstance().getContainerRegistry()
+## Data struct to group several quality changes instance containers together.
+#
+# Each group represents one "custom profile" as the user sees it, which
+# contains an instance container for the global stack and one instance
+# container per extruder.
+class QualityChangesGroup(QObject):
- def addNode(self, node: "QualityNode") -> None:
- extruder_position = node.getMetaDataEntry("position")
+ def __init__(self, name: str, quality_type: str, intent_category: str, parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+ self._name = name
+ self.quality_type = quality_type
+ self.intent_category = intent_category
+ self.is_available = False
+ self.metadata_for_global = {} # type: Dict[str, Any]
+ self.metadata_per_extruder = {} # type: Dict[int, Dict[str, Any]]
- if extruder_position is None and self.node_for_global is not None or extruder_position in self.nodes_for_extruders: #We would be overwriting another node.
- ConfigurationErrorMessage.getInstance().addFaultyContainers(node.getMetaDataEntry("id"))
- return
+ nameChanged = pyqtSignal()
- if extruder_position is None: # Then we're a global quality changes profile.
- self.node_for_global = node
- else: # This is an extruder's quality changes profile.
- self.nodes_for_extruders[extruder_position] = node
+ def setName(self, name: str) -> None:
+ if self._name != name:
+ self._name = name
+ self.nameChanged.emit()
+
+ @pyqtProperty(str, fset = setName, notify = nameChanged)
+ def name(self) -> str:
+ return self._name
def __str__(self) -> str:
- return "%s[<%s>, available = %s]" % (self.__class__.__name__, self.name, self.is_available)
+ return "{class_name}[{name}, available = {is_available}]".format(class_name = self.__class__.__name__, name = self.name, is_available = self.is_available)
diff --git a/cura/Machines/QualityGroup.py b/cura/Machines/QualityGroup.py
index f5bcbb0de8..58ba3acc63 100644
--- a/cura/Machines/QualityGroup.py
+++ b/cura/Machines/QualityGroup.py
@@ -1,32 +1,38 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, Optional, List, Set
from PyQt5.QtCore import QObject, pyqtSlot
+from UM.Logger import Logger
from UM.Util import parseBool
from cura.Machines.ContainerNode import ContainerNode
+## A QualityGroup represents a group of quality containers that must be applied
+# to each ContainerStack when it's used.
#
-# A QualityGroup represents a group of containers that must be applied to each ContainerStack when it's used.
-# Some concrete examples are Quality and QualityChanges: when we select quality type "normal", this quality type
-# must be applied to all stacks in a machine, although each stack can have different containers. Use an Ultimaker 3
-# as an example, suppose we choose quality type "normal", the actual InstanceContainers on each stack may look
-# as below:
-# GlobalStack ExtruderStack 1 ExtruderStack 2
-# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal
+# A concrete example: When there are two extruders and the user selects the
+# quality type "normal", this quality type must be applied to all stacks in a
+# machine, although each stack can have different containers. So one global
+# profile gets put on the global stack and one extruder profile gets put on
+# each extruder stack. This quality group then contains the following
+# profiles (for instance):
+# GlobalStack ExtruderStack 1 ExtruderStack 2
+# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal
#
-# This QualityGroup is mainly used in quality and quality_changes to group the containers that can be applied to
-# a machine, so when a quality/custom quality is selected, the container can be directly applied to each stack instead
-# of looking them up again.
-#
-class QualityGroup(QObject):
-
- def __init__(self, name: str, quality_type: str, parent = None) -> None:
- super().__init__(parent)
+# The purpose of these quality groups is to group the containers that can be
+# applied to a configuration, so that when a quality level is selected, the
+# container can directly be applied to each stack instead of looking them up
+# again.
+class QualityGroup:
+ ## Constructs a new group.
+ # \param name The user-visible name for the group.
+ # \param quality_type The quality level that each profile in this group
+ # has.
+ def __init__(self, name: str, quality_type: str) -> None:
self.name = name
self.node_for_global = None # type: Optional[ContainerNode]
self.nodes_for_extruders = {} # type: Dict[int, ContainerNode]
@@ -34,7 +40,6 @@ class QualityGroup(QObject):
self.is_available = False
self.is_experimental = False
- @pyqtSlot(result = str)
def getName(self) -> str:
return self.name
@@ -43,7 +48,7 @@ class QualityGroup(QObject):
for node in [self.node_for_global] + list(self.nodes_for_extruders.values()):
if node is None:
continue
- container = node.getContainer()
+ container = node.container
if container:
result.update(container.getAllKeys())
return result
@@ -60,6 +65,9 @@ class QualityGroup(QObject):
self.node_for_global = node
# Update is_experimental flag
+ if not node.container:
+ Logger.log("w", "Node {0} doesn't have a container.".format(node.container_id))
+ return
is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False))
self.is_experimental |= is_experimental
@@ -67,5 +75,8 @@ class QualityGroup(QObject):
self.nodes_for_extruders[position] = node
# Update is_experimental flag
+ if not node.container:
+ Logger.log("w", "Node {0} doesn't have a container.".format(node.container_id))
+ return
is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False))
self.is_experimental |= is_experimental
diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py
deleted file mode 100644
index 34cc9ce4b2..0000000000
--- a/cura/Machines/QualityManager.py
+++ /dev/null
@@ -1,550 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from typing import TYPE_CHECKING, Optional, cast, Dict, List, Set
-
-from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot
-
-from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
-from UM.Logger import Logger
-from UM.Util import parseBool
-from UM.Settings.InstanceContainer import InstanceContainer
-
-from cura.Settings.ExtruderStack import ExtruderStack
-
-from .QualityGroup import QualityGroup
-from .QualityNode import QualityNode
-
-if TYPE_CHECKING:
- from UM.Settings.Interfaces import DefinitionContainerInterface
- from cura.Settings.GlobalStack import GlobalStack
- from .QualityChangesGroup import QualityChangesGroup
- from cura.CuraApplication import CuraApplication
-
-
-#
-# Similar to MaterialManager, QualityManager maintains a number of maps and trees for quality profile lookup.
-# The models GUI and QML use are now only dependent on the QualityManager. That means as long as the data in
-# QualityManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI.
-#
-# For now, updating the lookup maps and trees here is very simple: we discard the old data completely and recreate them
-# again. This means the update is exactly the same as initialization. There are performance concerns about this approach
-# but so far the creation of the tables and maps is very fast and there is no noticeable slowness, we keep it like this
-# because it's simple.
-#
-class QualityManager(QObject):
-
- qualitiesUpdated = pyqtSignal()
-
- def __init__(self, application: "CuraApplication", parent = None) -> None:
- super().__init__(parent)
- self._application = application
- self._material_manager = self._application.getMaterialManager()
- self._container_registry = self._application.getContainerRegistry()
-
- self._empty_quality_container = self._application.empty_quality_container
- self._empty_quality_changes_container = self._application.empty_quality_changes_container
-
- # For quality lookup
- self._machine_nozzle_buildplate_material_quality_type_to_quality_dict = {} # type: Dict[str, QualityNode]
-
- # For quality_changes lookup
- self._machine_quality_type_to_quality_changes_dict = {} # type: Dict[str, QualityNode]
-
- self._default_machine_definition_id = "fdmprinter"
-
- self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged)
- self._container_registry.containerAdded.connect(self._onContainerMetadataChanged)
- self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged)
-
- # When a custom quality gets added/imported, there can be more than one InstanceContainers. In those cases,
- # we don't want to react on every container/metadata changed signal. The timer here is to buffer it a bit so
- # we don't react too many time.
- self._update_timer = QTimer(self)
- self._update_timer.setInterval(300)
- self._update_timer.setSingleShot(True)
- self._update_timer.timeout.connect(self._updateMaps)
-
- def initialize(self) -> None:
- # Initialize the lookup tree for quality profiles with following structure:
- # -> -> ->
- # ->
-
- self._machine_nozzle_buildplate_material_quality_type_to_quality_dict = {} # for quality lookup
- self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup
-
- quality_metadata_list = self._container_registry.findContainersMetadata(type = "quality")
- for metadata in quality_metadata_list:
- if metadata["id"] == "empty_quality":
- continue
-
- definition_id = metadata["definition"]
- quality_type = metadata["quality_type"]
-
- root_material_id = metadata.get("material")
- nozzle_name = metadata.get("variant")
- buildplate_name = metadata.get("buildplate")
- is_global_quality = metadata.get("global_quality", False)
- is_global_quality = is_global_quality or (root_material_id is None and nozzle_name is None and buildplate_name is None)
-
- # Sanity check: material+variant and is_global_quality cannot be present at the same time
- if is_global_quality and (root_material_id or nozzle_name):
- ConfigurationErrorMessage.getInstance().addFaultyContainers(metadata["id"])
- continue
-
- if definition_id not in self._machine_nozzle_buildplate_material_quality_type_to_quality_dict:
- self._machine_nozzle_buildplate_material_quality_type_to_quality_dict[definition_id] = QualityNode()
- machine_node = cast(QualityNode, self._machine_nozzle_buildplate_material_quality_type_to_quality_dict[definition_id])
-
- if is_global_quality:
- # For global qualities, save data in the machine node
- machine_node.addQualityMetadata(quality_type, metadata)
- continue
-
- current_node = machine_node
- intermediate_node_info_list = [nozzle_name, buildplate_name, root_material_id]
- current_intermediate_node_info_idx = 0
-
- while current_intermediate_node_info_idx < len(intermediate_node_info_list):
- node_name = intermediate_node_info_list[current_intermediate_node_info_idx]
- if node_name is not None:
- # There is specific information, update the current node to go deeper so we can add this quality
- # at the most specific branch in the lookup tree.
- if node_name not in current_node.children_map:
- current_node.children_map[node_name] = QualityNode()
- current_node = cast(QualityNode, current_node.children_map[node_name])
-
- current_intermediate_node_info_idx += 1
-
- current_node.addQualityMetadata(quality_type, metadata)
-
- # Initialize the lookup tree for quality_changes profiles with following structure:
- # -> ->
- quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes")
- for metadata in quality_changes_metadata_list:
- if metadata["id"] == "empty_quality_changes":
- continue
-
- machine_definition_id = metadata["definition"]
- quality_type = metadata["quality_type"]
-
- if machine_definition_id not in self._machine_quality_type_to_quality_changes_dict:
- self._machine_quality_type_to_quality_changes_dict[machine_definition_id] = QualityNode()
- machine_node = self._machine_quality_type_to_quality_changes_dict[machine_definition_id]
- machine_node.addQualityChangesMetadata(quality_type, metadata)
-
- Logger.log("d", "Lookup tables updated.")
- self.qualitiesUpdated.emit()
-
- def _updateMaps(self) -> None:
- self.initialize()
-
- def _onContainerMetadataChanged(self, container: InstanceContainer) -> None:
- self._onContainerChanged(container)
-
- def _onContainerChanged(self, container: InstanceContainer) -> None:
- container_type = container.getMetaDataEntry("type")
- if container_type not in ("quality", "quality_changes"):
- return
-
- # update the cache table
- self._update_timer.start()
-
- # Updates the given quality groups' availabilities according to which extruders are being used/ enabled.
- def _updateQualityGroupsAvailability(self, machine: "GlobalStack", quality_group_list) -> None:
- used_extruders = set()
- for i in range(machine.getProperty("machine_extruder_count", "value")):
- if str(i) in machine.extruders and machine.extruders[str(i)].isEnabled:
- used_extruders.add(str(i))
-
- # Update the "is_available" flag for each quality group.
- for quality_group in quality_group_list:
- is_available = True
- if quality_group.node_for_global is None:
- is_available = False
- if is_available:
- for position in used_extruders:
- if position not in quality_group.nodes_for_extruders:
- is_available = False
- break
-
- quality_group.is_available = is_available
-
- # Returns a dict of "custom profile name" -> QualityChangesGroup
- def getQualityChangesGroups(self, machine: "GlobalStack") -> dict:
- machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
-
- machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id)
- if not machine_node:
- Logger.log("i", "Cannot find node for machine def [%s] in QualityChanges lookup table", machine_definition_id)
- return dict()
-
- # Update availability for each QualityChangesGroup:
- # A custom profile is always available as long as the quality_type it's based on is available
- quality_group_dict = self.getQualityGroups(machine)
- available_quality_type_list = [qt for qt, qg in quality_group_dict.items() if qg.is_available]
-
- # Iterate over all quality_types in the machine node
- quality_changes_group_dict = dict()
- for quality_type, quality_changes_node in machine_node.quality_type_map.items():
- for quality_changes_name, quality_changes_group in quality_changes_node.children_map.items():
- quality_changes_group_dict[quality_changes_name] = quality_changes_group
- quality_changes_group.is_available = quality_type in available_quality_type_list
-
- return quality_changes_group_dict
-
- #
- # Gets all quality groups for the given machine. Both available and none available ones will be included.
- # It returns a dictionary with "quality_type"s as keys and "QualityGroup"s as values.
- # Whether a QualityGroup is available can be unknown via the field QualityGroup.is_available.
- # For more details, see QualityGroup.
- #
- def getQualityGroups(self, machine: "GlobalStack") -> Dict[str, QualityGroup]:
- machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
-
- # This determines if we should only get the global qualities for the global stack and skip the global qualities for the extruder stacks
- has_machine_specific_qualities = machine.getHasMachineQuality()
-
- # To find the quality container for the GlobalStack, check in the following fall-back manner:
- # (1) the machine-specific node
- # (2) the generic node
- machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(machine_definition_id)
- # Check if this machine has specific quality profiles for its extruders, if so, when looking up extruder
- # qualities, we should not fall back to use the global qualities.
- has_extruder_specific_qualities = False
- if machine_node:
- if machine_node.children_map:
- has_extruder_specific_qualities = True
-
- default_machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(self._default_machine_definition_id)
-
- nodes_to_check = [] # type: List[QualityNode]
- if machine_node is not None:
- nodes_to_check.append(machine_node)
- if default_machine_node is not None:
- nodes_to_check.append(default_machine_node)
-
- # Iterate over all quality_types in the machine node
- quality_group_dict = {}
- for node in nodes_to_check:
- if node and node.quality_type_map:
- quality_node = list(node.quality_type_map.values())[0]
- is_global_quality = parseBool(quality_node.getMetaDataEntry("global_quality", False))
- if not is_global_quality:
- continue
-
- for quality_type, quality_node in node.quality_type_map.items():
- quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
- quality_group.setGlobalNode(quality_node)
- quality_group_dict[quality_type] = quality_group
- break
-
- buildplate_name = machine.getBuildplateName()
-
- # Iterate over all extruders to find quality containers for each extruder
- for position, extruder in machine.extruders.items():
- nozzle_name = None
- if extruder.variant.getId() != "empty_variant":
- nozzle_name = extruder.variant.getName()
-
- # This is a list of root material IDs to use for searching for suitable quality profiles.
- # The root material IDs in this list are in prioritized order.
- root_material_id_list = []
- has_material = False # flag indicating whether this extruder has a material assigned
- root_material_id = None
- if extruder.material.getId() != "empty_material":
- has_material = True
- root_material_id = extruder.material.getMetaDataEntry("base_file")
- # Convert possible generic_pla_175 -> generic_pla
- root_material_id = self._material_manager.getRootMaterialIDWithoutDiameter(root_material_id)
- root_material_id_list.append(root_material_id)
-
- # Also try to get the fallback materials
- fallback_ids = self._material_manager.getFallBackMaterialIdsByMaterial(extruder.material)
-
- if fallback_ids:
- root_material_id_list.extend(fallback_ids)
-
- # Weed out duplicates while preserving the order.
- seen = set() # type: Set[str]
- root_material_id_list = [x for x in root_material_id_list if x not in seen and not seen.add(x)] # type: ignore
-
- # Here we construct a list of nodes we want to look for qualities with the highest priority first.
- # The use case is that, when we look for qualities for a machine, we first want to search in the following
- # order:
- # 1. machine-nozzle-buildplate-and-material-specific qualities if exist
- # 2. machine-nozzle-and-material-specific qualities if exist
- # 3. machine-nozzle-specific qualities if exist
- # 4. machine-material-specific qualities if exist
- # 5. machine-specific global qualities if exist, otherwise generic global qualities
- # NOTE: We DO NOT fail back to generic global qualities if machine-specific global qualities exist.
- # This is because when a machine defines its own global qualities such as Normal, Fine, etc.,
- # it is intended to maintain those specific qualities ONLY. If we still fail back to the generic
- # global qualities, there can be unimplemented quality types e.g. "coarse", and this is not
- # correct.
- # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into
- # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch
- # qualities from there.
- node_info_list_0 = [nozzle_name, buildplate_name, root_material_id] # type: List[Optional[str]]
- nodes_to_check = []
-
- # This function tries to recursively find the deepest (the most specific) branch and add those nodes to
- # the search list in the order described above. So, by iterating over that search node list, we first look
- # in the more specific branches and then the less specific (generic) ones.
- def addNodesToCheck(node: Optional[QualityNode], nodes_to_check_list: List[QualityNode], node_info_list, node_info_idx: int) -> None:
- if node is None:
- return
-
- if node_info_idx < len(node_info_list):
- node_name = node_info_list[node_info_idx]
- if node_name is not None:
- current_node = node.getChildNode(node_name)
- if current_node is not None and has_material:
- addNodesToCheck(current_node, nodes_to_check_list, node_info_list, node_info_idx + 1)
-
- if has_material:
- for rmid in root_material_id_list:
- material_node = node.getChildNode(rmid)
- if material_node:
- nodes_to_check_list.append(material_node)
- break
-
- nodes_to_check_list.append(node)
-
- addNodesToCheck(machine_node, nodes_to_check, node_info_list_0, 0)
-
- # The last fall back will be the global qualities (either from the machine-specific node or the generic
- # node), but we only use one. For details see the overview comments above.
-
- if machine_node is not None and machine_node.quality_type_map:
- nodes_to_check += [machine_node]
- elif default_machine_node is not None:
- nodes_to_check += [default_machine_node]
-
- for node_idx, node in enumerate(nodes_to_check):
- if node and node.quality_type_map:
- if has_extruder_specific_qualities:
- # Only include variant qualities; skip non global qualities
- quality_node = list(node.quality_type_map.values())[0]
- is_global_quality = parseBool(quality_node.getMetaDataEntry("global_quality", False))
- if is_global_quality:
- continue
-
- for quality_type, quality_node in node.quality_type_map.items():
- if quality_type not in quality_group_dict:
- quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
- quality_group_dict[quality_type] = quality_group
-
- quality_group = quality_group_dict[quality_type]
- if position not in quality_group.nodes_for_extruders:
- quality_group.setExtruderNode(position, quality_node)
-
- # If the machine has its own specific qualities, for extruders, it should skip the global qualities
- # and use the material/variant specific qualities.
- if has_extruder_specific_qualities:
- if node_idx == len(nodes_to_check) - 1:
- break
-
- # Update availabilities for each quality group
- self._updateQualityGroupsAvailability(machine, quality_group_dict.values())
-
- return quality_group_dict
-
- def getQualityGroupsForMachineDefinition(self, machine: "GlobalStack") -> Dict[str, QualityGroup]:
- machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
-
- # To find the quality container for the GlobalStack, check in the following fall-back manner:
- # (1) the machine-specific node
- # (2) the generic node
- machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(machine_definition_id)
- default_machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(
- self._default_machine_definition_id)
- nodes_to_check = [machine_node, default_machine_node]
-
- # Iterate over all quality_types in the machine node
- quality_group_dict = dict()
- for node in nodes_to_check:
- if node and node.quality_type_map:
- for quality_type, quality_node in node.quality_type_map.items():
- quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
- quality_group.setGlobalNode(quality_node)
- quality_group_dict[quality_type] = quality_group
- break
-
- return quality_group_dict
-
- def getDefaultQualityType(self, machine: "GlobalStack") -> Optional[QualityGroup]:
- preferred_quality_type = machine.definition.getMetaDataEntry("preferred_quality_type")
- quality_group_dict = self.getQualityGroups(machine)
- quality_group = quality_group_dict.get(preferred_quality_type)
- return quality_group
-
-
- #
- # Methods for GUI
- #
-
- #
- # Remove the given quality changes group.
- #
- @pyqtSlot(QObject)
- def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None:
- Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name)
- removed_quality_changes_ids = set()
- for node in quality_changes_group.getAllNodes():
- container_id = node.getMetaDataEntry("id")
- self._container_registry.removeContainer(container_id)
- removed_quality_changes_ids.add(container_id)
-
- # Reset all machines that have activated this quality changes to empty.
- for global_stack in self._container_registry.findContainerStacks(type = "machine"):
- if global_stack.qualityChanges.getId() in removed_quality_changes_ids:
- global_stack.qualityChanges = self._empty_quality_changes_container
- for extruder_stack in self._container_registry.findContainerStacks(type = "extruder_train"):
- if extruder_stack.qualityChanges.getId() in removed_quality_changes_ids:
- extruder_stack.qualityChanges = self._empty_quality_changes_container
-
- #
- # Rename a set of quality changes containers. Returns the new name.
- #
- @pyqtSlot(QObject, str, result = str)
- def renameQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", new_name: str) -> str:
- Logger.log("i", "Renaming QualityChangesGroup[%s] to [%s]", quality_changes_group.name, new_name)
- if new_name == quality_changes_group.name:
- Logger.log("i", "QualityChangesGroup name [%s] unchanged.", quality_changes_group.name)
- return new_name
-
- new_name = self._container_registry.uniqueName(new_name)
- for node in quality_changes_group.getAllNodes():
- container = node.getContainer()
- if container:
- container.setName(new_name)
-
- quality_changes_group.name = new_name
-
- self._application.getMachineManager().activeQualityChanged.emit()
- self._application.getMachineManager().activeQualityGroupChanged.emit()
-
- return new_name
-
- #
- # Duplicates the given quality.
- #
- @pyqtSlot(str, "QVariantMap")
- def duplicateQualityChanges(self, quality_changes_name: str, quality_model_item) -> None:
- global_stack = self._application.getGlobalContainerStack()
- if not global_stack:
- Logger.log("i", "No active global stack, cannot duplicate quality changes.")
- return
-
- quality_group = quality_model_item["quality_group"]
- quality_changes_group = quality_model_item["quality_changes_group"]
- if quality_changes_group is None:
- # create global quality changes only
- new_quality_changes = self._createQualityChanges(quality_group.quality_type, quality_changes_name,
- global_stack, None)
- self._container_registry.addContainer(new_quality_changes)
- else:
- new_name = self._container_registry.uniqueName(quality_changes_name)
- for node in quality_changes_group.getAllNodes():
- container = node.getContainer()
- if not container:
- continue
- new_id = self._container_registry.uniqueName(container.getId())
- self._container_registry.addContainer(container.duplicate(new_id, new_name))
-
- ## Create quality changes containers from the user containers in the active stacks.
- #
- # This will go through the global and extruder stacks and create quality_changes containers from
- # the user containers in each stack. These then replace the quality_changes containers in the
- # stack and clear the user settings.
- @pyqtSlot(str)
- def createQualityChanges(self, base_name: str) -> None:
- machine_manager = self._application.getMachineManager()
-
- global_stack = machine_manager.activeMachine
- if not global_stack:
- return
-
- active_quality_name = machine_manager.activeQualityOrQualityChangesName
- if active_quality_name == "":
- Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId())
- return
-
- machine_manager.blurSettings.emit()
- if base_name is None or base_name == "":
- base_name = active_quality_name
- unique_name = self._container_registry.uniqueName(base_name)
-
- # Go through the active stacks and create quality_changes containers from the user containers.
- stack_list = [global_stack] + list(global_stack.extruders.values())
- for stack in stack_list:
- user_container = stack.userChanges
- quality_container = stack.quality
- quality_changes_container = stack.qualityChanges
- if not quality_container or not quality_changes_container:
- Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId())
- continue
-
- quality_type = quality_container.getMetaDataEntry("quality_type")
- extruder_stack = None
- if isinstance(stack, ExtruderStack):
- extruder_stack = stack
- new_changes = self._createQualityChanges(quality_type, unique_name, global_stack, extruder_stack)
- from cura.Settings.ContainerManager import ContainerManager
- ContainerManager.getInstance()._performMerge(new_changes, quality_changes_container, clear_settings = False)
- ContainerManager.getInstance()._performMerge(new_changes, user_container)
-
- self._container_registry.addContainer(new_changes)
-
- #
- # Create a quality changes container with the given setup.
- #
- def _createQualityChanges(self, quality_type: str, new_name: str, machine: "GlobalStack",
- extruder_stack: Optional["ExtruderStack"]) -> "InstanceContainer":
- base_id = machine.definition.getId() if extruder_stack is None else extruder_stack.getId()
- new_id = base_id + "_" + new_name
- new_id = new_id.lower().replace(" ", "_")
- new_id = self._container_registry.uniqueName(new_id)
-
- # Create a new quality_changes container for the quality.
- quality_changes = InstanceContainer(new_id)
- quality_changes.setName(new_name)
- quality_changes.setMetaDataEntry("type", "quality_changes")
- quality_changes.setMetaDataEntry("quality_type", quality_type)
-
- # If we are creating a container for an extruder, ensure we add that to the container
- if extruder_stack is not None:
- quality_changes.setMetaDataEntry("position", extruder_stack.getMetaDataEntry("position"))
-
- # If the machine specifies qualities should be filtered, ensure we match the current criteria.
- machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
- quality_changes.setDefinition(machine_definition_id)
-
- quality_changes.setMetaDataEntry("setting_version", self._application.SettingVersion)
- return quality_changes
-
-
-#
-# Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given
-# machine. The rule is as follows:
-# 1. By default, the machine definition ID for quality container search will be "fdmprinter", which is the generic
-# machine.
-# 2. If a machine has its own machine quality (with "has_machine_quality = True"), we should use the given machine's
-# own machine definition ID for quality search.
-# Example: for an Ultimaker 3, the definition ID should be "ultimaker3".
-# 3. When condition (2) is met, AND the machine has "quality_definition" defined in its definition file, then the
-# definition ID specified in "quality_definition" should be used.
-# Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended
-# shares the same set of qualities profiles as Ultimaker 3.
-#
-def getMachineDefinitionIDForQualitySearch(machine_definition: "DefinitionContainerInterface",
- default_definition_id: str = "fdmprinter") -> str:
- machine_definition_id = default_definition_id
- if parseBool(machine_definition.getMetaDataEntry("has_machine_quality", False)):
- # Only use the machine's own quality definition ID if this machine has machine quality.
- machine_definition_id = machine_definition.getMetaDataEntry("quality_definition")
- if machine_definition_id is None:
- machine_definition_id = machine_definition.getId()
-
- return machine_definition_id
diff --git a/cura/Machines/QualityNode.py b/cura/Machines/QualityNode.py
index 991388a4bd..45cd898db5 100644
--- a/cura/Machines/QualityNode.py
+++ b/cura/Machines/QualityNode.py
@@ -1,38 +1,44 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional, Dict, cast, Any
+from typing import Union, TYPE_CHECKING
-from .ContainerNode import ContainerNode
-from .QualityChangesGroup import QualityChangesGroup
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from cura.Machines.ContainerNode import ContainerNode
+from cura.Machines.IntentNode import IntentNode
+import UM.FlameProfiler
+if TYPE_CHECKING:
+ from typing import Dict
+ from cura.Machines.MaterialNode import MaterialNode
+ from cura.Machines.MachineNode import MachineNode
+## Represents a quality profile in the container tree.
#
-# QualityNode is used for BOTH quality and quality_changes containers.
+# This may either be a normal quality profile or a global quality profile.
#
+# Its subcontainers are intent profiles.
class QualityNode(ContainerNode):
+ def __init__(self, container_id: str, parent: Union["MaterialNode", "MachineNode"]) -> None:
+ super().__init__(container_id)
+ self.parent = parent
+ self.intents = {} # type: Dict[str, IntentNode]
- def __init__(self, metadata: Optional[Dict[str, Any]] = None) -> None:
- super().__init__(metadata = metadata)
- self.quality_type_map = {} # type: Dict[str, QualityNode] # quality_type -> QualityNode for InstanceContainer
+ my_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = container_id)[0]
+ self.quality_type = my_metadata["quality_type"]
+ # The material type of the parent doesn't need to be the same as this due to generic fallbacks.
+ self._material = my_metadata.get("material")
+ self._loadAll()
- def getChildNode(self, child_key: str) -> Optional["QualityNode"]:
- return self.children_map.get(child_key)
+ @UM.FlameProfiler.profile
+ def _loadAll(self) -> None:
+ container_registry = ContainerRegistry.getInstance()
- def addQualityMetadata(self, quality_type: str, metadata: Dict[str, Any]):
- if quality_type not in self.quality_type_map:
- self.quality_type_map[quality_type] = QualityNode(metadata)
+ # Find all intent profiles that fit the current configuration.
+ from cura.Machines.MachineNode import MachineNode
+ if not isinstance(self.parent, MachineNode): # Not a global profile.
+ for intent in container_registry.findInstanceContainersMetadata(type = "intent", definition = self.parent.variant.machine.quality_definition, variant = self.parent.variant.variant_name, material = self._material, quality_type = self.quality_type):
+ self.intents[intent["id"]] = IntentNode(intent["id"], quality = self)
- def getQualityNode(self, quality_type: str) -> Optional["QualityNode"]:
- return self.quality_type_map.get(quality_type)
-
- def addQualityChangesMetadata(self, quality_type: str, metadata: Dict[str, Any]):
- if quality_type not in self.quality_type_map:
- self.quality_type_map[quality_type] = QualityNode()
- quality_type_node = self.quality_type_map[quality_type]
-
- name = metadata["name"]
- if name not in quality_type_node.children_map:
- quality_type_node.children_map[name] = QualityChangesGroup(name, quality_type)
- quality_changes_group = quality_type_node.children_map[name]
- cast(QualityChangesGroup, quality_changes_group).addNode(QualityNode(metadata))
+ self.intents["empty_intent"] = IntentNode("empty_intent", quality = self)
+ # Otherwise, there are no intents for global profiles.
\ No newline at end of file
diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py
deleted file mode 100644
index eaaa9fc5f0..0000000000
--- a/cura/Machines/VariantManager.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from collections import OrderedDict
-from typing import Optional, TYPE_CHECKING, Dict
-
-from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
-from UM.Logger import Logger
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Util import parseBool
-
-from cura.Machines.ContainerNode import ContainerNode
-from cura.Machines.VariantType import VariantType, ALL_VARIANT_TYPES
-from cura.Settings.GlobalStack import GlobalStack
-
-if TYPE_CHECKING:
- from UM.Settings.DefinitionContainer import DefinitionContainer
-
-
-#
-# VariantManager is THE place to look for a specific variant. It maintains two variant lookup tables with the following
-# structure:
-#
-# [machine_definition_id] -> [variant_type] -> [variant_name] -> ContainerNode(metadata / container)
-# Example: "ultimaker3" -> "buildplate" -> "Glass" (if present) -> ContainerNode
-# -> ...
-# -> "nozzle" -> "AA 0.4"
-# -> "BB 0.8"
-# -> ...
-#
-# [machine_definition_id] -> [machine_buildplate_type] -> ContainerNode(metadata / container)
-# Example: "ultimaker3" -> "glass" (this is different from the variant name) -> ContainerNode
-#
-# Note that the "container" field is not loaded in the beginning because it would defeat the purpose of lazy-loading.
-# A container is loaded when getVariant() is called to load a variant InstanceContainer.
-#
-class VariantManager:
-
- def __init__(self, container_registry: ContainerRegistry) -> None:
- self._container_registry = container_registry
-
- self._machine_to_variant_dict_map = dict() # type: Dict[str, Dict["VariantType", Dict[str, ContainerNode]]]
- self._machine_to_buildplate_dict_map = dict() # type: Dict[str, Dict[str, ContainerNode]]
-
- self._exclude_variant_id_list = ["empty_variant"]
-
- #
- # Initializes the VariantManager including:
- # - initializing the variant lookup table based on the metadata in ContainerRegistry.
- #
- def initialize(self) -> None:
- self._machine_to_variant_dict_map = OrderedDict()
- self._machine_to_buildplate_dict_map = OrderedDict()
-
- # Cache all variants from the container registry to a variant map for better searching and organization.
- variant_metadata_list = self._container_registry.findContainersMetadata(type = "variant")
- for variant_metadata in variant_metadata_list:
- if variant_metadata["id"] in self._exclude_variant_id_list:
- Logger.log("d", "Exclude variant [%s]", variant_metadata["id"])
- continue
-
- variant_name = variant_metadata["name"]
- variant_definition = variant_metadata["definition"]
- if variant_definition not in self._machine_to_variant_dict_map:
- self._machine_to_variant_dict_map[variant_definition] = OrderedDict()
- for variant_type in ALL_VARIANT_TYPES:
- self._machine_to_variant_dict_map[variant_definition][variant_type] = dict()
-
- try:
- variant_type = variant_metadata["hardware_type"]
- except KeyError:
- Logger.log("w", "Variant %s does not specify a hardware_type; assuming 'nozzle'", variant_metadata["id"])
- variant_type = VariantType.NOZZLE
- variant_type = VariantType(variant_type)
- variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type]
- if variant_name in variant_dict:
- # ERROR: duplicated variant name.
- ConfigurationErrorMessage.getInstance().addFaultyContainers(variant_metadata["id"])
- continue #Then ignore this variant. This now chooses one of the two variants arbitrarily and deletes the other one! No guarantees!
-
- variant_dict[variant_name] = ContainerNode(metadata = variant_metadata)
-
- # If the variant is a buildplate then fill also the buildplate map
- if variant_type == VariantType.BUILD_PLATE:
- if variant_definition not in self._machine_to_buildplate_dict_map:
- self._machine_to_buildplate_dict_map[variant_definition] = OrderedDict()
-
- variant_container = self._container_registry.findContainers(type = "variant", id = variant_metadata["id"])[0]
- buildplate_type = variant_container.getProperty("machine_buildplate_type", "value")
- if buildplate_type not in self._machine_to_buildplate_dict_map[variant_definition]:
- self._machine_to_variant_dict_map[variant_definition][buildplate_type] = dict()
-
- self._machine_to_buildplate_dict_map[variant_definition][buildplate_type] = variant_dict[variant_name]
-
- #
- # Gets the variant InstanceContainer with the given information.
- # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present.
- #
- def getVariantNode(self, machine_definition_id: str, variant_name: str,
- variant_type: Optional["VariantType"] = None) -> Optional["ContainerNode"]:
- if variant_type is None:
- variant_node = None
- variant_type_dict = self._machine_to_variant_dict_map[machine_definition_id]
- for variant_dict in variant_type_dict.values():
- if variant_name in variant_dict:
- variant_node = variant_dict[variant_name]
- break
- return variant_node
-
- return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {}).get(variant_name)
-
- def getVariantNodes(self, machine: "GlobalStack", variant_type: "VariantType") -> Dict[str, ContainerNode]:
- machine_definition_id = machine.definition.getId()
- return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {})
-
- #
- # Gets the default variant for the given machine definition.
- # If the optional GlobalStack is given, the metadata information will be fetched from the GlobalStack instead of
- # the DefinitionContainer. Because for machines such as UM2, you can enable Olsson Block, which will set
- # "has_variants" to True in the GlobalStack. In those cases, we need to fetch metadata from the GlobalStack or
- # it may not be correct.
- #
- def getDefaultVariantNode(self, machine_definition: "DefinitionContainer",
- variant_type: "VariantType",
- global_stack: Optional["GlobalStack"] = None) -> Optional["ContainerNode"]:
- machine_definition_id = machine_definition.getId()
- container_for_metadata_fetching = global_stack if global_stack is not None else machine_definition
-
- preferred_variant_name = None
- if variant_type == VariantType.BUILD_PLATE:
- if parseBool(container_for_metadata_fetching.getMetaDataEntry("has_variant_buildplates", False)):
- preferred_variant_name = container_for_metadata_fetching.getMetaDataEntry("preferred_variant_buildplate_name")
- else:
- if parseBool(container_for_metadata_fetching.getMetaDataEntry("has_variants", False)):
- preferred_variant_name = container_for_metadata_fetching.getMetaDataEntry("preferred_variant_name")
-
- node = None
- if preferred_variant_name:
- node = self.getVariantNode(machine_definition_id, preferred_variant_name, variant_type)
- return node
-
- def getBuildplateVariantNode(self, machine_definition_id: str, buildplate_type: str) -> Optional["ContainerNode"]:
- if machine_definition_id in self._machine_to_buildplate_dict_map:
- return self._machine_to_buildplate_dict_map[machine_definition_id].get(buildplate_type)
- return None
diff --git a/cura/Machines/VariantNode.py b/cura/Machines/VariantNode.py
new file mode 100644
index 0000000000..c9e3ec4913
--- /dev/null
+++ b/cura/Machines/VariantNode.py
@@ -0,0 +1,182 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import TYPE_CHECKING
+
+from UM.Logger import Logger
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Settings.Interfaces import ContainerInterface
+from UM.Signal import Signal
+
+from cura.Machines.ContainerNode import ContainerNode
+from cura.Machines.MaterialNode import MaterialNode
+
+import UM.FlameProfiler
+
+if TYPE_CHECKING:
+ from typing import Dict
+ from cura.Machines.MachineNode import MachineNode
+
+
+## This class represents an extruder variant in the container tree.
+#
+# The subnodes of these nodes are materials.
+#
+# This node contains materials with ALL filament diameters underneath it. The
+# tree of this variant is not specific to one global stack, so because the
+# list of materials can be different per stack depending on the compatible
+# material diameter setting, we cannot filter them here. Filtering must be
+# done in the model.
+class VariantNode(ContainerNode):
+ def __init__(self, container_id: str, machine: "MachineNode") -> None:
+ super().__init__(container_id)
+ self.machine = machine
+ self.materials = {} # type: Dict[str, MaterialNode] # Mapping material base files to their nodes.
+ self.materialsChanged = Signal()
+
+ container_registry = ContainerRegistry.getInstance()
+ self.variant_name = container_registry.findContainersMetadata(id = container_id)[0]["name"] # Store our own name so that we can filter more easily.
+ container_registry.containerAdded.connect(self._materialAdded)
+ container_registry.containerRemoved.connect(self._materialRemoved)
+ self._loadAll()
+
+ ## (Re)loads all materials under this variant.
+ @UM.FlameProfiler.profile
+ def _loadAll(self) -> None:
+ container_registry = ContainerRegistry.getInstance()
+
+ if not self.machine.has_materials:
+ self.materials["empty_material"] = MaterialNode("empty_material", variant = self)
+ return # There should not be any materials loaded for this printer.
+
+ # Find all the materials for this variant's name.
+ else: # Printer has its own material profiles. Look for material profiles with this printer's definition.
+ base_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = "fdmprinter")
+ printer_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id, variant_name = None)
+ variant_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id, variant_name = self.variant_name) # If empty_variant, this won't return anything.
+ materials_per_base_file = {material["base_file"]: material for material in base_materials}
+ materials_per_base_file.update({material["base_file"]: material for material in printer_specific_materials}) # Printer-specific profiles override global ones.
+ materials_per_base_file.update({material["base_file"]: material for material in variant_specific_materials}) # Variant-specific profiles override all of those.
+ materials = list(materials_per_base_file.values())
+
+ # Filter materials based on the exclude_materials property.
+ filtered_materials = [material for material in materials if material["id"] not in self.machine.exclude_materials]
+
+ for material in filtered_materials:
+ base_file = material["base_file"]
+ if base_file not in self.materials:
+ self.materials[base_file] = MaterialNode(material["id"], variant = self)
+ self.materials[base_file].materialChanged.connect(self.materialsChanged)
+ if not self.materials:
+ self.materials["empty_material"] = MaterialNode("empty_material", variant = self)
+
+ ## Finds the preferred material for this printer with this nozzle in one of
+ # the extruders.
+ #
+ # If the preferred material is not available, an arbitrary material is
+ # returned. If there is a configuration mistake (like a typo in the
+ # preferred material) this returns a random available material. If there
+ # are no available materials, this will return the empty material node.
+ # \param approximate_diameter The desired approximate diameter of the
+ # material.
+ # \return The node for the preferred material, or any arbitrary material
+ # if there is no match.
+ def preferredMaterial(self, approximate_diameter: int) -> MaterialNode:
+ for base_material, material_node in self.materials.items():
+ if self.machine.preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
+ return material_node
+
+ # First fallback: Check if we should be checking for the 175 variant.
+ if approximate_diameter == 2:
+ preferred_material = self.machine.preferred_material + "_175"
+ for base_material, material_node in self.materials.items():
+ if preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
+ return material_node
+
+ # Second fallback: Choose any material with matching diameter.
+ for material_node in self.materials.values():
+ if material_node.getMetaDataEntry("approximate_diameter") and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
+ Logger.log("w", "Could not find preferred material %s, falling back to whatever works", self.machine.preferred_material)
+ return material_node
+
+ fallback = next(iter(self.materials.values())) # Should only happen with empty material node.
+ Logger.log("w", "Could not find preferred material {preferred_material} with diameter {diameter} for variant {variant_id}, falling back to {fallback}.".format(
+ preferred_material = self.machine.preferred_material,
+ diameter = approximate_diameter,
+ variant_id = self.container_id,
+ fallback = fallback.container_id
+ ))
+ return fallback
+
+ ## When a material gets added to the set of profiles, we need to update our
+ # tree here.
+ @UM.FlameProfiler.profile
+ def _materialAdded(self, container: ContainerInterface) -> None:
+ if container.getMetaDataEntry("type") != "material":
+ return # Not interested.
+ if not ContainerRegistry.getInstance().findContainersMetadata(id = container.getId()):
+ # CURA-6889
+ # containerAdded and removed signals may be triggered in the next event cycle. If a container gets added
+ # and removed in the same event cycle, in the next cycle, the connections should just ignore the signals.
+ # The check here makes sure that the container in the signal still exists.
+ Logger.log("d", "Got container added signal for container [%s] but it no longer exists, do nothing.",
+ container.getId())
+ return
+ if not self.machine.has_materials:
+ return # We won't add any materials.
+ material_definition = container.getMetaDataEntry("definition")
+
+ base_file = container.getMetaDataEntry("base_file")
+ if base_file in self.machine.exclude_materials:
+ return # Material is forbidden for this printer.
+ if base_file not in self.materials: # Completely new base file. Always better than not having a file as long as it matches our set-up.
+ if material_definition != "fdmprinter" and material_definition != self.machine.container_id:
+ return
+ material_variant = container.getMetaDataEntry("variant_name")
+ if material_variant is not None and material_variant != self.variant_name:
+ return
+ else: # We already have this base profile. Replace the base profile if the new one is more specific.
+ new_definition = container.getMetaDataEntry("definition")
+ if new_definition == "fdmprinter":
+ return # Just as unspecific or worse.
+ material_variant = container.getMetaDataEntry("variant_name")
+ if new_definition != self.machine.container_id or material_variant != self.variant_name:
+ return # Doesn't match this set-up.
+ original_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = self.materials[base_file].container_id)[0]
+ if "variant_name" in original_metadata or material_variant is None:
+ return # Original was already specific or just as unspecific as the new one.
+
+ if "empty_material" in self.materials:
+ del self.materials["empty_material"]
+ self.materials[base_file] = MaterialNode(container.getId(), variant = self)
+ self.materials[base_file].materialChanged.connect(self.materialsChanged)
+ self.materialsChanged.emit(self.materials[base_file])
+
+ @UM.FlameProfiler.profile
+ def _materialRemoved(self, container: ContainerInterface) -> None:
+ if container.getMetaDataEntry("type") != "material":
+ return # Only interested in materials.
+ base_file = container.getMetaDataEntry("base_file")
+ if base_file not in self.materials:
+ return # We don't track this material anyway. No need to remove it.
+
+ original_node = self.materials[base_file]
+ del self.materials[base_file]
+ self.materialsChanged.emit(original_node)
+
+ # Now a different material from the same base file may have been hidden because it was not as specific as the one we deleted.
+ # Search for any submaterials from that base file that are still left.
+ materials_same_base_file = ContainerRegistry.getInstance().findContainersMetadata(base_file = base_file)
+ if materials_same_base_file:
+ most_specific_submaterial = materials_same_base_file[0]
+ for submaterial in materials_same_base_file:
+ if submaterial["definition"] == self.machine.container_id:
+ if most_specific_submaterial["definition"] == "fdmprinter":
+ most_specific_submaterial = submaterial
+ if most_specific_submaterial.get("variant_name", "empty") == "empty" and submaterial.get("variant_name", "empty") == self.variant_name:
+ most_specific_submaterial = submaterial
+ self.materials[base_file] = MaterialNode(most_specific_submaterial["id"], variant = self)
+ self.materialsChanged.emit(self.materials[base_file])
+
+ if not self.materials: # The last available material just got deleted and there is nothing with the same base file to replace it.
+ self.materials["empty_material"] = MaterialNode("empty_material", variant = self)
+ self.materialsChanged.emit(self.materials["empty_material"])
\ No newline at end of file
diff --git a/cura/MultiplyObjectsJob.py b/cura/MultiplyObjectsJob.py
index e71bbf6668..5c25f70336 100644
--- a/cura/MultiplyObjectsJob.py
+++ b/cura/MultiplyObjectsJob.py
@@ -2,10 +2,12 @@
# Cura is released under the terms of the LGPLv3 or higher.
import copy
+from typing import List
from UM.Job import Job
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Message import Message
+from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
@@ -23,7 +25,7 @@ class MultiplyObjectsJob(Job):
self._count = count
self._min_offset = min_offset
- def run(self):
+ def run(self) -> None:
status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime=0,
dismissable=False, progress=0, title = i18n_catalog.i18nc("@info:title", "Placing Objects"))
status_message.show()
@@ -33,13 +35,15 @@ class MultiplyObjectsJob(Job):
current_progress = 0
global_container_stack = Application.getInstance().getGlobalContainerStack()
+ if global_container_stack is None:
+ return # We can't do anything in this case.
machine_width = global_container_stack.getProperty("machine_width", "value")
machine_depth = global_container_stack.getProperty("machine_depth", "value")
root = scene.getRoot()
scale = 0.5
arranger = Arrange.create(x = machine_width, y = machine_depth, scene_root = root, scale = scale, min_offset = self._min_offset)
- processed_nodes = []
+ processed_nodes = [] # type: List[SceneNode]
nodes = []
not_fit_count = 0
@@ -67,7 +71,11 @@ class MultiplyObjectsJob(Job):
new_node = copy.deepcopy(node)
solution_found = False
if not node_too_big:
- solution_found = arranger.findNodePlacement(new_node, offset_shape_arr, hull_shape_arr)
+ if offset_shape_arr is not None and hull_shape_arr is not None:
+ solution_found = arranger.findNodePlacement(new_node, offset_shape_arr, hull_shape_arr)
+ else:
+ # The node has no shape, so no need to arrange it. The solution is simple: Do nothing.
+ solution_found = True
if node_too_big or not solution_found:
found_solution_for_all = False
diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py
index f4a29962a4..9fc01ba50b 100644
--- a/cura/OAuth2/AuthorizationHelpers.py
+++ b/cura/OAuth2/AuthorizationHelpers.py
@@ -50,6 +50,7 @@ class AuthorizationHelpers:
# \param refresh_token:
# \return An AuthenticationResponse object.
def getAccessTokenUsingRefreshToken(self, refresh_token: str) -> "AuthenticationResponse":
+ Logger.log("d", "Refreshing the access token.")
data = {
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
"redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "",
@@ -98,7 +99,7 @@ class AuthorizationHelpers:
})
except requests.exceptions.ConnectionError:
# Connection was suddenly dropped. Nothing we can do about that.
- Logger.log("w", "Something failed while attempting to parse the JWT token")
+ Logger.logException("w", "Something failed while attempting to parse the JWT token")
return None
if token_request.status_code not in (200, 201):
Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text)
diff --git a/cura/OAuth2/AuthorizationRequestHandler.py b/cura/OAuth2/AuthorizationRequestHandler.py
index 66ecfc2787..83b94ed586 100644
--- a/cura/OAuth2/AuthorizationRequestHandler.py
+++ b/cura/OAuth2/AuthorizationRequestHandler.py
@@ -25,6 +25,10 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
self.authorization_callback = None # type: Optional[Callable[[AuthenticationResponse], None]]
self.verification_code = None # type: Optional[str]
+ # CURA-6609: Some browser seems to issue a HEAD instead of GET request as the callback.
+ def do_HEAD(self) -> None:
+ self.do_GET()
+
def do_GET(self) -> None:
# Extract values from the query string.
parsed_url = urlparse(self.path)
diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py
index a4214ee958..0848623410 100644
--- a/cura/OAuth2/AuthorizationService.py
+++ b/cura/OAuth2/AuthorizationService.py
@@ -2,12 +2,14 @@
# Cura is released under the terms of the LGPLv3 or higher.
import json
-import webbrowser
from datetime import datetime, timedelta
from typing import Optional, TYPE_CHECKING
from urllib.parse import urlencode
+
import requests.exceptions
+from PyQt5.QtCore import QUrl
+from PyQt5.QtGui import QDesktopServices
from UM.Logger import Logger
from UM.Message import Message
@@ -34,6 +36,8 @@ class AuthorizationService:
# Emit signal when authentication failed.
onAuthenticationError = Signal()
+ accessTokenChanged = Signal()
+
def __init__(self, settings: "OAuth2Settings", preferences: Optional["Preferences"] = None) -> None:
self._settings = settings
self._auth_helpers = AuthorizationHelpers(settings)
@@ -68,6 +72,7 @@ class AuthorizationService:
self._user_profile = self._parseJWT()
except requests.exceptions.ConnectionError:
# Unable to get connection, can't login.
+ Logger.logException("w", "Unable to validate user data with the remote server.")
return None
if not self._user_profile and self._auth_data:
@@ -83,6 +88,7 @@ class AuthorizationService:
def _parseJWT(self) -> Optional["UserProfile"]:
if not self._auth_data or self._auth_data.access_token is None:
# If no auth data exists, we should always log in again.
+ Logger.log("d", "There was no auth data or access token")
return None
user_data = self._auth_helpers.parseJWT(self._auth_data.access_token)
if user_data:
@@ -90,12 +96,16 @@ class AuthorizationService:
return user_data
# The JWT was expired or invalid and we should request a new one.
if self._auth_data.refresh_token is None:
+ Logger.log("w", "There was no refresh token in the auth data.")
return None
self._auth_data = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
if not self._auth_data or self._auth_data.access_token is None:
+ Logger.log("w", "Unable to use the refresh token to get a new access token.")
# The token could not be refreshed using the refresh token. We should login again.
return None
-
+ # Ensure it gets stored as otherwise we only have it in memory. The stored refresh token has been deleted
+ # from the server already.
+ self._storeAuthData(self._auth_data)
return self._auth_helpers.parseJWT(self._auth_data.access_token)
## Get the access token as provided by the repsonse data.
@@ -124,7 +134,8 @@ class AuthorizationService:
self._storeAuthData(response)
self.onAuthStateChanged.emit(logged_in = True)
else:
- self.onAuthStateChanged(logged_in = False)
+ Logger.log("w", "Failed to get a new access token from the server.")
+ self.onAuthStateChanged.emit(logged_in = False)
## Delete the authentication data that we have stored locally (eg; logout)
def deleteAuthData(self) -> None:
@@ -154,7 +165,7 @@ class AuthorizationService:
})
# Open the authorization page in a new browser window.
- webbrowser.open_new("{}?{}".format(self._auth_url, query_string))
+ QDesktopServices.openUrl(QUrl("{}?{}".format(self._auth_url, query_string)))
# Start a local web server to receive the callback URL on.
self._server.start(verification_code)
@@ -186,14 +197,13 @@ class AuthorizationService:
self._unable_to_get_data_message.hide()
self._unable_to_get_data_message = Message(i18n_catalog.i18nc("@info", "Unable to reach the Ultimaker account server."), title = i18n_catalog.i18nc("@info:title", "Warning"))
- self._unable_to_get_data_message.addAction("retry", i18n_catalog.i18nc("@action:button", "Retry"), "[no_icon]", "[no_description]")
- self._unable_to_get_data_message.actionTriggered.connect(self._onMessageActionTriggered)
self._unable_to_get_data_message.show()
except ValueError:
Logger.logException("w", "Could not load auth data from preferences")
## Store authentication data in preferences.
def _storeAuthData(self, auth_data: Optional[AuthenticationResponse] = None) -> None:
+ Logger.log("d", "Attempting to store the auth data")
if self._preferences is None:
Logger.log("e", "Unable to save authentication data, since no preference has been set!")
return
@@ -206,6 +216,5 @@ class AuthorizationService:
self._user_profile = None
self._preferences.resetPreference(self._settings.AUTH_DATA_PREFERENCE_KEY)
- def _onMessageActionTriggered(self, _, action):
- if action == "retry":
- self.loadAuthDataFromPreferences()
+ self.accessTokenChanged.emit()
+
diff --git a/cura/OAuth2/LocalAuthorizationServer.py b/cura/OAuth2/LocalAuthorizationServer.py
index 25b2435012..a80b0deb28 100644
--- a/cura/OAuth2/LocalAuthorizationServer.py
+++ b/cura/OAuth2/LocalAuthorizationServer.py
@@ -63,6 +63,10 @@ class LocalAuthorizationServer:
Logger.log("d", "Stopping local oauth2 web server...")
if self._web_server:
- self._web_server.server_close()
+ try:
+ self._web_server.server_close()
+ except OSError:
+ # OS error can happen if the socket was already closed. We really don't care about that case.
+ pass
self._web_server = None
self._web_server_thread = None
diff --git a/cura/ObjectsModel.py b/cura/ObjectsModel.py
deleted file mode 100644
index f9f923b31d..0000000000
--- a/cura/ObjectsModel.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import QTimer
-
-from UM.Application import Application
-from UM.Qt.ListModel import ListModel
-from UM.Scene.Camera import Camera
-from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
-from UM.Scene.SceneNode import SceneNode
-from UM.Scene.Selection import Selection
-from UM.i18n import i18nCatalog
-from collections import defaultdict
-
-catalog = i18nCatalog("cura")
-
-
-## Keep track of all objects in the project
-class ObjectsModel(ListModel):
- def __init__(self):
- super().__init__()
-
- Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSceneDelayed)
- Application.getInstance().getPreferences().preferenceChanged.connect(self._updateDelayed)
-
- self._update_timer = QTimer()
- self._update_timer.setInterval(200)
- self._update_timer.setSingleShot(True)
- self._update_timer.timeout.connect(self._update)
-
- self._build_plate_number = -1
-
- def setActiveBuildPlate(self, nr):
- if self._build_plate_number != nr:
- self._build_plate_number = nr
- self._update()
-
- def _updateSceneDelayed(self, source):
- if not isinstance(source, Camera):
- self._update_timer.start()
-
- def _updateDelayed(self, *args):
- self._update_timer.start()
-
- def _update(self, *args):
- nodes = []
- filter_current_build_plate = Application.getInstance().getPreferences().getValue("view/filter_current_build_plate")
- active_build_plate_number = self._build_plate_number
- group_nr = 1
- name_count_dict = defaultdict(int)
-
- for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
- if not isinstance(node, SceneNode):
- continue
- if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
- continue
- if node.getParent() and node.getParent().callDecoration("isGroup"):
- continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
- if not node.callDecoration("isSliceable") and not node.callDecoration("isGroup"):
- continue
- node_build_plate_number = node.callDecoration("getBuildPlateNumber")
- if filter_current_build_plate and node_build_plate_number != active_build_plate_number:
- continue
-
- if not node.callDecoration("isGroup"):
- name = node.getName()
-
- else:
- name = catalog.i18nc("@label", "Group #{group_nr}").format(group_nr = str(group_nr))
- group_nr += 1
-
- if hasattr(node, "isOutsideBuildArea"):
- is_outside_build_area = node.isOutsideBuildArea()
- else:
- is_outside_build_area = False
-
- #check if we already have an instance of the object based on name
- name_count_dict[name] += 1
- name_count = name_count_dict[name]
-
- if name_count > 1:
- name = "{0}({1})".format(name, name_count-1)
- node.setName(name)
-
- nodes.append({
- "name": name,
- "isSelected": Selection.isSelected(node),
- "isOutsideBuildArea": is_outside_build_area,
- "buildPlateNumber": node_build_plate_number,
- "node": node
- })
-
- nodes = sorted(nodes, key=lambda n: n["name"])
- self.setItems(nodes)
-
- self.itemsChanged.emit()
-
- @staticmethod
- def createObjectsModel():
- return ObjectsModel()
diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py
index a08f3ed2bf..b77e1f3982 100644
--- a/cura/OneAtATimeIterator.py
+++ b/cura/OneAtATimeIterator.py
@@ -1,149 +1,127 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import sys
+from typing import List
-from shapely import affinity
-from shapely.geometry import Polygon
-
-from UM.Scene.Iterator.Iterator import Iterator
+from UM.Scene.Iterator import Iterator
from UM.Scene.SceneNode import SceneNode
+from functools import cmp_to_key
+## Iterator that returns a list of nodes in the order that they need to be printed
+# If there is no solution an empty list is returned.
+# Take note that the list of nodes can have children (that may or may not contain mesh data)
+class OneAtATimeIterator(Iterator.Iterator):
+ def __init__(self, scene_node) -> None:
+ super().__init__(scene_node) # Call super to make multiple inheritance work.
+ self._hit_map = [[]] # type: List[List[bool]] # For each node, which other nodes this hits. A grid of booleans on which nodes hit which.
+ self._original_node_list = [] # type: List[SceneNode] # The nodes that need to be checked for collisions.
-# Iterator that determines the object print order when one-at a time mode is enabled.
-#
-# In one-at-a-time mode, only one extruder can be enabled to print. In order to maximize the number of objects we can
-# print, we need to print from the corner that's closest to the extruder that's being used. Here is an illustration:
-#
-# +--------------------------------+
-# | |
-# | |
-# | | - Rectangle represents the complete print head including fans, etc.
-# | X X | y - X's are the nozzles
-# | (1) (2) | ^
-# | | |
-# +--------------------------------+ +--> x
-#
-# In this case, the nozzles are symmetric, nozzle (1) is closer to the bottom left corner while (2) is closer to the
-# bottom right. If we use nozzle (1) to print, then we better off printing from the bottom left corner so the print
-# head will not collide into an object on its top-right side, which is a very large unused area. Following the same
-# logic, if we are printing with nozzle (2), then it's better to print from the bottom-right side.
-#
-# This iterator determines the print order following the rules above.
-#
-class OneAtATimeIterator(Iterator):
-
- def __init__(self, scene_node):
- from cura.CuraApplication import CuraApplication
- self._global_stack = CuraApplication.getInstance().getGlobalContainerStack()
- self._original_node_list = []
-
- super().__init__(scene_node) # Call super to make multiple inheritance work.
-
- def getMachineNearestCornerToExtruder(self, global_stack):
- head_and_fans_coordinates = global_stack.getHeadAndFansCoordinates()
-
- used_extruder = None
- for extruder in global_stack.extruders.values():
- if extruder.isEnabled:
- used_extruder = extruder
- break
-
- extruder_offsets = [used_extruder.getProperty("machine_nozzle_offset_x", "value"),
- used_extruder.getProperty("machine_nozzle_offset_y", "value")]
-
- # find the corner that's closest to the origin
- min_distance2 = sys.maxsize
- min_coord = None
- for coord in head_and_fans_coordinates:
- x = coord[0] - extruder_offsets[0]
- y = coord[1] - extruder_offsets[1]
-
- distance2 = x**2 + y**2
- if distance2 <= min_distance2:
- min_distance2 = distance2
- min_coord = coord
-
- return min_coord
-
- def _checkForCollisions(self) -> bool:
- all_nodes = []
- for node in self._scene_node.getChildren():
- if not issubclass(type(node), SceneNode):
- continue
- convex_hull = node.callDecoration("getConvexHullHead")
- if not convex_hull:
- continue
-
- bounding_box = node.getBoundingBox()
- if not bounding_box:
- continue
- from UM.Math.Polygon import Polygon
- bounding_box_polygon = Polygon([[bounding_box.left, bounding_box.front],
- [bounding_box.left, bounding_box.back],
- [bounding_box.right, bounding_box.back],
- [bounding_box.right, bounding_box.front]])
-
- all_nodes.append({"node": node,
- "bounding_box": bounding_box_polygon,
- "convex_hull": convex_hull})
-
- has_collisions = False
- for i, node_dict in enumerate(all_nodes):
- for j, other_node_dict in enumerate(all_nodes):
- if i == j:
- continue
- if node_dict["bounding_box"].intersectsPolygon(other_node_dict["convex_hull"]):
- has_collisions = True
- break
-
- if has_collisions:
- break
-
- return has_collisions
-
- def _fillStack(self):
- min_coord = self.getMachineNearestCornerToExtruder(self._global_stack)
- transform_x = -int(round(min_coord[0] / abs(min_coord[0])))
- transform_y = -int(round(min_coord[1] / abs(min_coord[1])))
-
- machine_size = [self._global_stack.getProperty("machine_width", "value"),
- self._global_stack.getProperty("machine_depth", "value")]
-
- def flip_x(polygon):
- tm2 = [-1, 0, 0, 1, 0, 0]
- return affinity.affine_transform(affinity.translate(polygon, xoff = -machine_size[0]), tm2)
-
- def flip_y(polygon):
- tm2 = [1, 0, 0, -1, 0, 0]
- return affinity.affine_transform(affinity.translate(polygon, yoff = -machine_size[1]), tm2)
-
- if self._checkForCollisions():
- self._node_stack = []
- return
-
+ ## Fills the ``_node_stack`` with a list of scene nodes that need to be
+ # printed in order.
+ def _fillStack(self) -> None:
node_list = []
for node in self._scene_node.getChildren():
if not issubclass(type(node), SceneNode):
continue
- convex_hull = node.callDecoration("getConvexHull")
- if convex_hull:
- xmin = min(x for x, _ in convex_hull._points)
- xmax = max(x for x, _ in convex_hull._points)
- ymin = min(y for _, y in convex_hull._points)
- ymax = max(y for _, y in convex_hull._points)
+ if node.callDecoration("getConvexHull"):
+ node_list.append(node)
- convex_hull_polygon = Polygon.from_bounds(xmin, ymin, xmax, ymax)
- if transform_x < 0:
- convex_hull_polygon = flip_x(convex_hull_polygon)
- if transform_y < 0:
- convex_hull_polygon = flip_y(convex_hull_polygon)
- node_list.append({"node": node,
- "min_coord": [convex_hull_polygon.bounds[0], convex_hull_polygon.bounds[1]],
- })
+ if len(node_list) < 2:
+ self._node_stack = node_list[:]
+ return
- node_list = sorted(node_list, key = lambda d: d["min_coord"])
+ # Copy the list
+ self._original_node_list = node_list[:]
- self._node_stack = [d["node"] for d in node_list]
+ ## Initialise the hit map (pre-compute all hits between all objects)
+ self._hit_map = [[self._checkHit(i,j) for i in node_list] for j in node_list]
+
+ # Check if we have to files that block each other. If this is the case, there is no solution!
+ for a in range(0, len(node_list)):
+ for b in range(0, len(node_list)):
+ if a != b and self._hit_map[a][b] and self._hit_map[b][a]:
+ return
+
+ # Sort the original list so that items that block the most other objects are at the beginning.
+ # This does not decrease the worst case running time, but should improve it in most cases.
+ sorted(node_list, key = cmp_to_key(self._calculateScore))
+
+ todo_node_list = [_ObjectOrder([], node_list)]
+ while len(todo_node_list) > 0:
+ current = todo_node_list.pop()
+ for node in current.todo:
+ # Check if the object can be placed with what we have and still allows for a solution in the future
+ if not self._checkHitMultiple(node, current.order) and not self._checkBlockMultiple(node, current.todo):
+ # We found a possible result. Create new todo & order list.
+ new_todo_list = current.todo[:]
+ new_todo_list.remove(node)
+ new_order = current.order[:] + [node]
+ if len(new_todo_list) == 0:
+ # We have no more nodes to check, so quit looking.
+ self._node_stack = new_order
+ return
+ todo_node_list.append(_ObjectOrder(new_order, new_todo_list))
+ self._node_stack = [] #No result found!
+
+
+ # Check if first object can be printed before the provided list (using the hit map)
+ def _checkHitMultiple(self, node: SceneNode, other_nodes: List[SceneNode]) -> bool:
+ node_index = self._original_node_list.index(node)
+ for other_node in other_nodes:
+ other_node_index = self._original_node_list.index(other_node)
+ if self._hit_map[node_index][other_node_index]:
+ return True
+ return False
+
+ ## Check for a node whether it hits any of the other nodes.
+ # \param node The node to check whether it collides with the other nodes.
+ # \param other_nodes The nodes to check for collisions.
+ def _checkBlockMultiple(self, node: SceneNode, other_nodes: List[SceneNode]) -> bool:
+ node_index = self._original_node_list.index(node)
+ for other_node in other_nodes:
+ other_node_index = self._original_node_list.index(other_node)
+ if self._hit_map[other_node_index][node_index] and node_index != other_node_index:
+ return True
+ return False
+
+ ## Calculate score simply sums the number of other objects it 'blocks'
+ def _calculateScore(self, a: SceneNode, b: SceneNode) -> int:
+ score_a = sum(self._hit_map[self._original_node_list.index(a)])
+ score_b = sum(self._hit_map[self._original_node_list.index(b)])
+ return score_a - score_b
+
+ ## Checks if A can be printed before B
+ def _checkHit(self, a: SceneNode, b: SceneNode) -> bool:
+ if a == b:
+ return False
+
+ a_hit_hull = a.callDecoration("getConvexHullBoundary")
+ b_hit_hull = b.callDecoration("getConvexHullHeadFull")
+ overlap = a_hit_hull.intersectsPolygon(b_hit_hull)
+
+ if overlap:
+ return True
+
+ # Adhesion areas must never overlap, regardless of printing order
+ # This would cause over-extrusion
+ a_hit_hull = a.callDecoration("getAdhesionArea")
+ b_hit_hull = b.callDecoration("getAdhesionArea")
+ overlap = a_hit_hull.intersectsPolygon(b_hit_hull)
+
+ if overlap:
+ return True
+ else:
+ return False
+
+
+## Internal object used to keep track of a possible order in which to print objects.
+class _ObjectOrder:
+ ## Creates the _ObjectOrder instance.
+ # \param order List of indices in which to print objects, ordered by printing
+ # order.
+ # \param todo: List of indices which are not yet inserted into the order list.
+ def __init__(self, order: List[SceneNode], todo: List[SceneNode]):
+ self.order = order
+ self.todo = todo
diff --git a/cura/Operations/PlatformPhysicsOperation.py b/cura/Operations/PlatformPhysicsOperation.py
index 75c5b437bc..9571679c3c 100644
--- a/cura/Operations/PlatformPhysicsOperation.py
+++ b/cura/Operations/PlatformPhysicsOperation.py
@@ -29,4 +29,4 @@ class PlatformPhysicsOperation(Operation):
return group
def __repr__(self):
- return "PlatformPhysicsOperation(translation = {0})".format(self._translation)
+ return "PlatformPhysicsOp.(trans.={0})".format(self._translation)
diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py
index 8fffac4501..a411478b16 100755
--- a/cura/PlatformPhysics.py
+++ b/cura/PlatformPhysics.py
@@ -17,6 +17,7 @@ from cura.Scene import ZOffsetDecorator
import random # used for list shuffling
+
class PlatformPhysics:
def __init__(self, controller, volume):
super().__init__()
@@ -49,18 +50,20 @@ class PlatformPhysics:
return
root = self._controller.getScene().getRoot()
+ build_volume = Application.getInstance().getBuildVolume()
+ build_volume.updateNodeBoundaryCheck()
# Keep a list of nodes that are moving. We use this so that we don't move two intersecting objects in the
# same direction.
transformed_nodes = []
- # We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A.
- # By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve.
nodes = list(BreadthFirstIterator(root))
# Only check nodes inside build area.
nodes = [node for node in nodes if (hasattr(node, "_outside_buildarea") and not node._outside_buildarea)]
+ # We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A.
+ # By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve.
random.shuffle(nodes)
for node in nodes:
if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None:
@@ -76,7 +79,7 @@ class PlatformPhysics:
move_vector = move_vector.set(y = -bbox.bottom + z_offset)
# If there is no convex hull for the node, start calculating it and continue.
- if not node.getDecorator(ConvexHullDecorator):
+ if not node.getDecorator(ConvexHullDecorator) and not node.callDecoration("isNonPrintingMesh"):
node.addDecorator(ConvexHullDecorator())
# only push away objects if this node is a printing mesh
@@ -160,7 +163,6 @@ class PlatformPhysics:
op.push()
# After moving, we have to evaluate the boundary checks for nodes
- build_volume = Application.getInstance().getBuildVolume()
build_volume.updateNodeBoundaryCheck()
def _onToolOperationStarted(self, tool):
diff --git a/cura/PreviewPass.py b/cura/PreviewPass.py
index befb52ee5e..58205ba708 100644
--- a/cura/PreviewPass.py
+++ b/cura/PreviewPass.py
@@ -1,7 +1,8 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional, TYPE_CHECKING
+from typing import Optional, TYPE_CHECKING, cast
+
from UM.Application import Application
from UM.Resources import Resources
@@ -12,6 +13,7 @@ from UM.View.RenderBatch import RenderBatch
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+from cura.Scene.CuraSceneNode import CuraSceneNode
if TYPE_CHECKING:
from UM.View.GL.ShaderProgram import ShaderProgram
@@ -44,9 +46,9 @@ class PreviewPass(RenderPass):
self._renderer = Application.getInstance().getRenderer()
- self._shader = None #type: Optional[ShaderProgram]
- self._non_printing_shader = None #type: Optional[ShaderProgram]
- self._support_mesh_shader = None #type: Optional[ShaderProgram]
+ self._shader = None # type: Optional[ShaderProgram]
+ self._non_printing_shader = None # type: Optional[ShaderProgram]
+ self._support_mesh_shader = None # type: Optional[ShaderProgram]
self._scene = Application.getInstance().getController().getScene()
# Set the camera to be used by this render pass
@@ -62,6 +64,7 @@ class PreviewPass(RenderPass):
self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0])
self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0])
self._shader.setUniformValue("u_shininess", 20.0)
+ self._shader.setUniformValue("u_faceId", -1) # Don't render any selected faces in the preview.
if not self._non_printing_shader:
if self._non_printing_shader:
@@ -83,30 +86,31 @@ class PreviewPass(RenderPass):
batch_support_mesh = RenderBatch(self._support_mesh_shader)
# Fill up the batch with objects that can be sliced.
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
- if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
- per_mesh_stack = node.callDecoration("getStack")
- if node.callDecoration("isNonThumbnailVisibleMesh"):
- # Non printing mesh
- continue
- elif per_mesh_stack is not None and per_mesh_stack.getProperty("support_mesh", "value"):
- # Support mesh
- uniforms = {}
- shade_factor = 0.6
- diffuse_color = node.getDiffuseColor()
- diffuse_color2 = [
- diffuse_color[0] * shade_factor,
- diffuse_color[1] * shade_factor,
- diffuse_color[2] * shade_factor,
- 1.0]
- uniforms["diffuse_color"] = prettier_color(diffuse_color)
- uniforms["diffuse_color_2"] = diffuse_color2
- batch_support_mesh.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
- else:
- # Normal scene node
- uniforms = {}
- uniforms["diffuse_color"] = prettier_color(node.getDiffuseColor())
- batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
+ for node in DepthFirstIterator(self._scene.getRoot()):
+ if hasattr(node, "_outside_buildarea") and not getattr(node, "_outside_buildarea"):
+ if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
+ per_mesh_stack = node.callDecoration("getStack")
+ if node.callDecoration("isNonThumbnailVisibleMesh"):
+ # Non printing mesh
+ continue
+ elif per_mesh_stack is not None and per_mesh_stack.getProperty("support_mesh", "value"):
+ # Support mesh
+ uniforms = {}
+ shade_factor = 0.6
+ diffuse_color = cast(CuraSceneNode, node).getDiffuseColor()
+ diffuse_color2 = [
+ diffuse_color[0] * shade_factor,
+ diffuse_color[1] * shade_factor,
+ diffuse_color[2] * shade_factor,
+ 1.0]
+ uniforms["diffuse_color"] = prettier_color(diffuse_color)
+ uniforms["diffuse_color_2"] = diffuse_color2
+ batch_support_mesh.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
+ else:
+ # Normal scene node
+ uniforms = {}
+ uniforms["diffuse_color"] = prettier_color(cast(CuraSceneNode, node).getDiffuseColor())
+ batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
self.bind()
diff --git a/cura/PrinterOutput/FirmwareUpdater.py b/cura/PrinterOutput/FirmwareUpdater.py
index c6d9513ee0..56e260a7f0 100644
--- a/cura/PrinterOutput/FirmwareUpdater.py
+++ b/cura/PrinterOutput/FirmwareUpdater.py
@@ -9,7 +9,7 @@ from typing import Union
MYPY = False
if MYPY:
- from cura.PrinterOutputDevice import PrinterOutputDevice
+ from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
class FirmwareUpdater(QObject):
firmwareProgressChanged = pyqtSignal()
@@ -20,7 +20,7 @@ class FirmwareUpdater(QObject):
self._output_device = output_device
- self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True)
+ self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True, name = "FirmwareUpdateThread")
self._firmware_file = ""
self._firmware_progress = 0
@@ -43,7 +43,7 @@ class FirmwareUpdater(QObject):
## Cleanup after a succesful update
def _cleanupAfterUpdate(self) -> None:
# Clean up for next attempt.
- self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True)
+ self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True, name = "FirmwareUpdateThread")
self._firmware_file = ""
self._onFirmwareProgress(100)
self._setFirmwareUpdateState(FirmwareUpdateState.completed)
diff --git a/cura/PrinterOutput/GenericOutputController.py b/cura/PrinterOutput/GenericOutputController.py
index 1cb416787c..c160459776 100644
--- a/cura/PrinterOutput/GenericOutputController.py
+++ b/cura/PrinterOutput/GenericOutputController.py
@@ -3,14 +3,15 @@
from typing import TYPE_CHECKING, Set, Union, Optional
-from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
from PyQt5.QtCore import QTimer
+from .PrinterOutputController import PrinterOutputController
+
if TYPE_CHECKING:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
- from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
- from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
+ from .Models.PrintJobOutputModel import PrintJobOutputModel
+ from .Models.PrinterOutputModel import PrinterOutputModel
+ from .PrinterOutputDevice import PrinterOutputDevice
+ from .Models.ExtruderOutputModel import ExtruderOutputModel
class GenericOutputController(PrinterOutputController):
@@ -54,7 +55,7 @@ class GenericOutputController(PrinterOutputController):
self._preheat_hotends_timer.stop()
for extruder in self._preheat_hotends:
extruder.updateIsPreheating(False)
- self._preheat_hotends = set() # type: Set[ExtruderOutputModel]
+ self._preheat_hotends = set()
def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed) -> None:
self._output_device.sendCommand("G91")
@@ -158,7 +159,7 @@ class GenericOutputController(PrinterOutputController):
def _onPreheatHotendsTimerFinished(self) -> None:
for extruder in self._preheat_hotends:
self.setTargetHotendTemperature(extruder.getPrinter(), extruder.getPosition(), 0)
- self._preheat_hotends = set() #type: Set[ExtruderOutputModel]
+ self._preheat_hotends = set()
# Cancel any ongoing preheating timers, without setting back the temperature to 0
# This can be used eg at the start of a print
@@ -166,7 +167,7 @@ class GenericOutputController(PrinterOutputController):
if self._preheat_hotends_timer.isActive():
for extruder in self._preheat_hotends:
extruder.updateIsPreheating(False)
- self._preheat_hotends = set() #type: Set[ExtruderOutputModel]
+ self._preheat_hotends = set()
self._preheat_hotends_timer.stop()
diff --git a/cura/PrinterOutput/MaterialOutputModel.py b/cura/PrinterOutput/MaterialOutputModel.py
deleted file mode 100644
index 64ebd3c94c..0000000000
--- a/cura/PrinterOutput/MaterialOutputModel.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot
-
-
-class MaterialOutputModel(QObject):
- def __init__(self, guid, type, color, brand, name, parent = None):
- super().__init__(parent)
- self._guid = guid
- self._type = type
- self._color = color
- self._brand = brand
- self._name = name
-
- @pyqtProperty(str, constant = True)
- def guid(self):
- return self._guid
-
- @pyqtProperty(str, constant=True)
- def type(self):
- return self._type
-
- @pyqtProperty(str, constant=True)
- def brand(self):
- return self._brand
-
- @pyqtProperty(str, constant=True)
- def color(self):
- return self._color
-
- @pyqtProperty(str, constant=True)
- def name(self):
- return self._name
\ No newline at end of file
diff --git a/cura/PrinterOutput/ExtruderConfigurationModel.py b/cura/PrinterOutput/Models/ExtruderConfigurationModel.py
similarity index 70%
rename from cura/PrinterOutput/ExtruderConfigurationModel.py
rename to cura/PrinterOutput/Models/ExtruderConfigurationModel.py
index da0ad6b0b2..4a1cf4916f 100644
--- a/cura/PrinterOutput/ExtruderConfigurationModel.py
+++ b/cura/PrinterOutput/Models/ExtruderConfigurationModel.py
@@ -4,7 +4,7 @@ from typing import Optional
from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
-from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
+from .MaterialOutputModel import MaterialOutputModel
class ExtruderConfigurationModel(QObject):
@@ -25,15 +25,16 @@ class ExtruderConfigurationModel(QObject):
return self._position
def setMaterial(self, material: Optional[MaterialOutputModel]) -> None:
- if self._hotend_id != material:
- self._material = material
- self.extruderConfigurationChanged.emit()
+ if material is None or self._material == material:
+ return
+ self._material = material
+ self.extruderConfigurationChanged.emit()
@pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged)
def activeMaterial(self) -> Optional[MaterialOutputModel]:
return self._material
- @pyqtProperty(QObject, fset=setMaterial, notify=extruderConfigurationChanged)
+ @pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged)
def material(self) -> Optional[MaterialOutputModel]:
return self._material
@@ -62,9 +63,26 @@ class ExtruderConfigurationModel(QObject):
return " ".join(message_chunks)
def __eq__(self, other) -> bool:
- return hash(self) == hash(other)
+ if not isinstance(other, ExtruderConfigurationModel):
+ return False
+
+ if self._position != other.position:
+ return False
+ # Empty materials should be ignored for comparison
+ if self.activeMaterial is not None and other.activeMaterial is not None:
+ if self.activeMaterial.guid != other.activeMaterial.guid:
+ if self.activeMaterial.guid != "" and other.activeMaterial.guid != "":
+ return False
+ else:
+ # At this point there is no material, so it doesn't matter what the hotend is.
+ return True
+
+ if self.hotendID != other.hotendID:
+ return False
+
+ return True
# Calculating a hash function using the position of the extruder, the material GUID and the hotend id to check if is
# unique within a set
def __hash__(self):
- return hash(self._position) ^ (hash(self._material.guid) if self._material is not None else hash(0)) ^ hash(self._hotend_id)
\ No newline at end of file
+ return hash(self._position) ^ (hash(self._material.guid) if self._material is not None else hash(0)) ^ hash(self._hotend_id)
diff --git a/cura/PrinterOutput/ExtruderOutputModel.py b/cura/PrinterOutput/Models/ExtruderOutputModel.py
similarity index 95%
rename from cura/PrinterOutput/ExtruderOutputModel.py
rename to cura/PrinterOutput/Models/ExtruderOutputModel.py
index 30d53bbd85..889e140312 100644
--- a/cura/PrinterOutput/ExtruderOutputModel.py
+++ b/cura/PrinterOutput/Models/ExtruderOutputModel.py
@@ -1,14 +1,15 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
-from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
-
from typing import Optional, TYPE_CHECKING
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
+
+from .ExtruderConfigurationModel import ExtruderConfigurationModel
+
if TYPE_CHECKING:
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
- from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
+ from .MaterialOutputModel import MaterialOutputModel
+ from .PrinterOutputModel import PrinterOutputModel
class ExtruderOutputModel(QObject):
diff --git a/cura/PrinterOutput/Models/MaterialOutputModel.py b/cura/PrinterOutput/Models/MaterialOutputModel.py
new file mode 100644
index 0000000000..3714824a89
--- /dev/null
+++ b/cura/PrinterOutput/Models/MaterialOutputModel.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2017 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional
+
+from PyQt5.QtCore import pyqtProperty, QObject
+
+
+class MaterialOutputModel(QObject):
+ def __init__(self, guid: Optional[str], type: str, color: str, brand: str, name: str, parent = None) -> None:
+ super().__init__(parent)
+ self._guid = guid
+ self._type = type
+ self._color = color
+ self._brand = brand
+ self._name = name
+
+ @pyqtProperty(str, constant = True)
+ def guid(self) -> str:
+ return self._guid if self._guid else ""
+
+ @pyqtProperty(str, constant = True)
+ def type(self) -> str:
+ return self._type
+
+ @pyqtProperty(str, constant = True)
+ def brand(self) -> str:
+ return self._brand
+
+ @pyqtProperty(str, constant = True)
+ def color(self) -> str:
+ return self._color
+
+ @pyqtProperty(str, constant = True)
+ def name(self) -> str:
+ return self._name
+
+ def __eq__(self, other):
+ if self is other:
+ return True
+ if type(other) is not MaterialOutputModel:
+ return False
+
+ return self.guid == other.guid and self.type == other.type and self.brand == other.brand and self.color == other.color and self.name == other.name
diff --git a/cura/PrinterOutput/Models/PrintJobOutputModel.py b/cura/PrinterOutput/Models/PrintJobOutputModel.py
new file mode 100644
index 0000000000..b4296a5494
--- /dev/null
+++ b/cura/PrinterOutput/Models/PrintJobOutputModel.py
@@ -0,0 +1,171 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional, TYPE_CHECKING, List
+
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot, QUrl
+from PyQt5.QtGui import QImage
+
+if TYPE_CHECKING:
+ from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
+ from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
+ from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
+
+
+class PrintJobOutputModel(QObject):
+ stateChanged = pyqtSignal()
+ timeTotalChanged = pyqtSignal()
+ timeElapsedChanged = pyqtSignal()
+ nameChanged = pyqtSignal()
+ keyChanged = pyqtSignal()
+ assignedPrinterChanged = pyqtSignal()
+ ownerChanged = pyqtSignal()
+ configurationChanged = pyqtSignal()
+ previewImageChanged = pyqtSignal()
+ compatibleMachineFamiliesChanged = pyqtSignal()
+
+ def __init__(self, output_controller: "PrinterOutputController", key: str = "", name: str = "", parent = None) -> None:
+ super().__init__(parent)
+ self._output_controller = output_controller
+ self._state = ""
+ self._time_total = 0
+ self._time_elapsed = 0
+ self._name = name # Human readable name
+ self._key = key # Unique identifier
+ self._assigned_printer = None # type: Optional[PrinterOutputModel]
+ self._owner = "" # Who started/owns the print job?
+
+ self._configuration = None # type: Optional[PrinterConfigurationModel]
+ self._compatible_machine_families = [] # type: List[str]
+ self._preview_image_id = 0
+
+ self._preview_image = None # type: Optional[QImage]
+
+ @pyqtProperty("QStringList", notify=compatibleMachineFamiliesChanged)
+ def compatibleMachineFamilies(self):
+ # Hack; Some versions of cluster will return a family more than once...
+ return list(set(self._compatible_machine_families))
+
+ def setCompatibleMachineFamilies(self, compatible_machine_families: List[str]) -> None:
+ if self._compatible_machine_families != compatible_machine_families:
+ self._compatible_machine_families = compatible_machine_families
+ self.compatibleMachineFamiliesChanged.emit()
+
+ @pyqtProperty(QUrl, notify=previewImageChanged)
+ def previewImageUrl(self):
+ self._preview_image_id += 1
+ # There is an image provider that is called "print_job_preview". In order to ensure that the image qml object, that
+ # requires a QUrl to function, updates correctly we add an increasing number. This causes to see the QUrl
+ # as new (instead of relying on cached version and thus forces an update.
+ temp = "image://print_job_preview/" + str(self._preview_image_id) + "/" + self._key
+ return QUrl(temp, QUrl.TolerantMode)
+
+ def getPreviewImage(self) -> Optional[QImage]:
+ return self._preview_image
+
+ def updatePreviewImage(self, preview_image: Optional[QImage]) -> None:
+ if self._preview_image != preview_image:
+ self._preview_image = preview_image
+ self.previewImageChanged.emit()
+
+ @pyqtProperty(QObject, notify=configurationChanged)
+ def configuration(self) -> Optional["PrinterConfigurationModel"]:
+ return self._configuration
+
+ def updateConfiguration(self, configuration: Optional["PrinterConfigurationModel"]) -> None:
+ if self._configuration != configuration:
+ self._configuration = configuration
+ self.configurationChanged.emit()
+
+ @pyqtProperty(str, notify=ownerChanged)
+ def owner(self):
+ return self._owner
+
+ def updateOwner(self, owner):
+ if self._owner != owner:
+ self._owner = owner
+ self.ownerChanged.emit()
+
+ @pyqtProperty(QObject, notify=assignedPrinterChanged)
+ def assignedPrinter(self):
+ return self._assigned_printer
+
+ def updateAssignedPrinter(self, assigned_printer: Optional["PrinterOutputModel"]) -> None:
+ if self._assigned_printer != assigned_printer:
+ old_printer = self._assigned_printer
+ self._assigned_printer = assigned_printer
+ if old_printer is not None:
+ # If the previously assigned printer is set, this job is moved away from it.
+ old_printer.updateActivePrintJob(None)
+ self.assignedPrinterChanged.emit()
+
+ @pyqtProperty(str, notify=keyChanged)
+ def key(self):
+ return self._key
+
+ def updateKey(self, key: str):
+ if self._key != key:
+ self._key = key
+ self.keyChanged.emit()
+
+ @pyqtProperty(str, notify = nameChanged)
+ def name(self):
+ return self._name
+
+ def updateName(self, name: str):
+ if self._name != name:
+ self._name = name
+ self.nameChanged.emit()
+
+ @pyqtProperty(int, notify = timeTotalChanged)
+ def timeTotal(self) -> int:
+ return self._time_total
+
+ @pyqtProperty(int, notify = timeElapsedChanged)
+ def timeElapsed(self) -> int:
+ return self._time_elapsed
+
+ @pyqtProperty(int, notify = timeElapsedChanged)
+ def timeRemaining(self) -> int:
+ # Never get a negative time remaining
+ return max(self.timeTotal - self.timeElapsed, 0)
+
+ @pyqtProperty(float, notify = timeElapsedChanged)
+ def progress(self) -> float:
+ result = float(self.timeElapsed) / max(self.timeTotal, 1.0) # Prevent a division by zero exception.
+ return min(result, 1.0) # Never get a progress past 1.0
+
+ @pyqtProperty(str, notify=stateChanged)
+ def state(self) -> str:
+ return self._state
+
+ @pyqtProperty(bool, notify=stateChanged)
+ def isActive(self) -> bool:
+ inactive_states = [
+ "pausing",
+ "paused",
+ "resuming",
+ "wait_cleanup"
+ ]
+ if self.state in inactive_states and self.timeRemaining > 0:
+ return False
+ return True
+
+ def updateTimeTotal(self, new_time_total):
+ if self._time_total != new_time_total:
+ self._time_total = new_time_total
+ self.timeTotalChanged.emit()
+
+ def updateTimeElapsed(self, new_time_elapsed):
+ if self._time_elapsed != new_time_elapsed:
+ self._time_elapsed = new_time_elapsed
+ self.timeElapsedChanged.emit()
+
+ def updateState(self, new_state):
+ if self._state != new_state:
+ self._state = new_state
+ self.stateChanged.emit()
+
+ @pyqtSlot(str)
+ def setState(self, state):
+ self._output_controller.setJobState(self, state)
diff --git a/cura/PrinterOutput/ConfigurationModel.py b/cura/PrinterOutput/Models/PrinterConfigurationModel.py
similarity index 72%
rename from cura/PrinterOutput/ConfigurationModel.py
rename to cura/PrinterOutput/Models/PrinterConfigurationModel.py
index 312e3cffb0..52c7b6f960 100644
--- a/cura/PrinterOutput/ConfigurationModel.py
+++ b/cura/PrinterOutput/Models/PrinterConfigurationModel.py
@@ -6,10 +6,10 @@ from typing import List
MYPY = False
if MYPY:
- from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
+ from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
-class ConfigurationModel(QObject):
+class PrinterConfigurationModel(QObject):
configurationChanged = pyqtSignal()
@@ -19,14 +19,14 @@ class ConfigurationModel(QObject):
self._extruder_configurations = [] # type: List[ExtruderConfigurationModel]
self._buildplate_configuration = ""
- def setPrinterType(self, printer_type):
+ def setPrinterType(self, printer_type: str) -> None:
self._printer_type = printer_type
@pyqtProperty(str, fset = setPrinterType, notify = configurationChanged)
def printerType(self) -> str:
return self._printer_type
- def setExtruderConfigurations(self, extruder_configurations: List["ExtruderConfigurationModel"]):
+ def setExtruderConfigurations(self, extruder_configurations: List["ExtruderConfigurationModel"]) -> None:
if self._extruder_configurations != extruder_configurations:
self._extruder_configurations = extruder_configurations
@@ -40,7 +40,7 @@ class ConfigurationModel(QObject):
return self._extruder_configurations
def setBuildplateConfiguration(self, buildplate_configuration: str) -> None:
- if self._buildplate_configuration != buildplate_configuration:
+ if self._buildplate_configuration != buildplate_configuration:
self._buildplate_configuration = buildplate_configuration
self.configurationChanged.emit()
@@ -58,6 +58,14 @@ class ConfigurationModel(QObject):
return False
return self._printer_type != ""
+ def hasAnyMaterialLoaded(self) -> bool:
+ if not self.isValid():
+ return False
+ for configuration in self._extruder_configurations:
+ if configuration.activeMaterial and configuration.activeMaterial.type != "empty":
+ return True
+ return False
+
def __str__(self):
message_chunks = []
message_chunks.append("Printer type: " + self._printer_type)
@@ -71,7 +79,23 @@ class ConfigurationModel(QObject):
return "\n".join(message_chunks)
def __eq__(self, other):
- return hash(self) == hash(other)
+ if not isinstance(other, PrinterConfigurationModel):
+ return False
+
+ if self.printerType != other.printerType:
+ return False
+
+ if self.buildplateConfiguration != other.buildplateConfiguration:
+ return False
+
+ if len(self.extruderConfigurations) != len(other.extruderConfigurations):
+ return False
+
+ for self_extruder, other_extruder in zip(sorted(self._extruder_configurations, key=lambda x: x.position), sorted(other.extruderConfigurations, key=lambda x: x.position)):
+ if self_extruder != other_extruder:
+ return False
+
+ return True
## The hash function is used to compare and create unique sets. The configuration is unique if the configuration
# of the extruders is unique (the order of the extruders matters), and the type and buildplate is the same.
@@ -86,4 +110,4 @@ class ConfigurationModel(QObject):
if first_extruder:
extruder_hash &= hash(first_extruder)
- return hash(self._printer_type) ^ extruder_hash ^ hash(self._buildplate_configuration)
\ No newline at end of file
+ return hash(self._printer_type) ^ extruder_hash ^ hash(self._buildplate_configuration)
diff --git a/cura/PrinterOutput/Models/PrinterOutputModel.py b/cura/PrinterOutput/Models/PrinterOutputModel.py
new file mode 100644
index 0000000000..37135bf663
--- /dev/null
+++ b/cura/PrinterOutput/Models/PrinterOutputModel.py
@@ -0,0 +1,350 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot, QUrl
+from typing import List, Dict, Optional, TYPE_CHECKING
+from UM.Math.Vector import Vector
+from cura.PrinterOutput.Peripheral import Peripheral
+from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
+from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
+from UM.Logger import Logger
+
+if TYPE_CHECKING:
+ from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
+ from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
+
+
+class PrinterOutputModel(QObject):
+ bedTemperatureChanged = pyqtSignal()
+ targetBedTemperatureChanged = pyqtSignal()
+ isPreheatingChanged = pyqtSignal()
+ stateChanged = pyqtSignal()
+ activePrintJobChanged = pyqtSignal()
+ nameChanged = pyqtSignal()
+ headPositionChanged = pyqtSignal()
+ keyChanged = pyqtSignal()
+ typeChanged = pyqtSignal()
+ buildplateChanged = pyqtSignal()
+ cameraUrlChanged = pyqtSignal()
+ configurationChanged = pyqtSignal()
+ canUpdateFirmwareChanged = pyqtSignal()
+
+ def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = "") -> None:
+ super().__init__(parent)
+ self._bed_temperature = -1 # type: float # Use -1 for no heated bed.
+ self._target_bed_temperature = 0 # type: float
+ self._name = ""
+ self._key = "" # Unique identifier
+ self._unique_name = "" # Unique name (used in Connect)
+ self._controller = output_controller
+ self._controller.canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
+ self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
+ self._active_printer_configuration = PrinterConfigurationModel() # Indicates the current configuration setup in this printer
+ self._head_position = Vector(0, 0, 0)
+ self._active_print_job = None # type: Optional[PrintJobOutputModel]
+ self._firmware_version = firmware_version
+ self._printer_state = "unknown"
+ self._is_preheating = False
+ self._printer_type = ""
+ self._buildplate = ""
+ self._peripherals = [] # type: List[Peripheral]
+
+ self._active_printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
+ self._extruders]
+ self._active_printer_configuration.configurationChanged.connect(self.configurationChanged)
+ self._available_printer_configurations = [] # type: List[PrinterConfigurationModel]
+
+ self._camera_url = QUrl() # type: QUrl
+
+ @pyqtProperty(str, constant = True)
+ def firmwareVersion(self) -> str:
+ return self._firmware_version
+
+ def setCameraUrl(self, camera_url: "QUrl") -> None:
+ if self._camera_url != camera_url:
+ self._camera_url = camera_url
+ self.cameraUrlChanged.emit()
+
+ @pyqtProperty(QUrl, fset = setCameraUrl, notify = cameraUrlChanged)
+ def cameraUrl(self) -> "QUrl":
+ return self._camera_url
+
+ def updateIsPreheating(self, pre_heating: bool) -> None:
+ if self._is_preheating != pre_heating:
+ self._is_preheating = pre_heating
+ self.isPreheatingChanged.emit()
+
+ @pyqtProperty(bool, notify=isPreheatingChanged)
+ def isPreheating(self) -> bool:
+ return self._is_preheating
+
+ @pyqtProperty(str, notify = typeChanged)
+ def type(self) -> str:
+ return self._printer_type
+
+ def updateType(self, printer_type: str) -> None:
+ if self._printer_type != printer_type:
+ self._printer_type = printer_type
+ self._active_printer_configuration.printerType = self._printer_type
+ self.typeChanged.emit()
+ self.configurationChanged.emit()
+
+ @pyqtProperty(str, notify = buildplateChanged)
+ def buildplate(self) -> str:
+ return self._buildplate
+
+ def updateBuildplate(self, buildplate: str) -> None:
+ if self._buildplate != buildplate:
+ self._buildplate = buildplate
+ self._active_printer_configuration.buildplateConfiguration = self._buildplate
+ self.buildplateChanged.emit()
+ self.configurationChanged.emit()
+
+ @pyqtProperty(str, notify=keyChanged)
+ def key(self) -> str:
+ return self._key
+
+ def updateKey(self, key: str) -> None:
+ if self._key != key:
+ self._key = key
+ self.keyChanged.emit()
+
+ @pyqtSlot()
+ def homeHead(self) -> None:
+ self._controller.homeHead(self)
+
+ @pyqtSlot()
+ def homeBed(self) -> None:
+ self._controller.homeBed(self)
+
+ @pyqtSlot(str)
+ def sendRawCommand(self, command: str) -> None:
+ self._controller.sendRawCommand(self, command)
+
+ @pyqtProperty("QVariantList", constant = True)
+ def extruders(self) -> List["ExtruderOutputModel"]:
+ return self._extruders
+
+ @pyqtProperty(QVariant, notify = headPositionChanged)
+ def headPosition(self) -> Dict[str, float]:
+ return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z}
+
+ def updateHeadPosition(self, x: float, y: float, z: float) -> None:
+ if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z:
+ self._head_position = Vector(x, y, z)
+ self.headPositionChanged.emit()
+
+ @pyqtProperty(float, float, float)
+ @pyqtProperty(float, float, float, float)
+ def setHeadPosition(self, x: float, y: float, z: float, speed: float = 3000) -> None:
+ self.updateHeadPosition(x, y, z)
+ self._controller.setHeadPosition(self, x, y, z, speed)
+
+ @pyqtProperty(float)
+ @pyqtProperty(float, float)
+ def setHeadX(self, x: float, speed: float = 3000) -> None:
+ self.updateHeadPosition(x, self._head_position.y, self._head_position.z)
+ self._controller.setHeadPosition(self, x, self._head_position.y, self._head_position.z, speed)
+
+ @pyqtProperty(float)
+ @pyqtProperty(float, float)
+ def setHeadY(self, y: float, speed: float = 3000) -> None:
+ self.updateHeadPosition(self._head_position.x, y, self._head_position.z)
+ self._controller.setHeadPosition(self, self._head_position.x, y, self._head_position.z, speed)
+
+ @pyqtProperty(float)
+ @pyqtProperty(float, float)
+ def setHeadZ(self, z: float, speed:float = 3000) -> None:
+ self.updateHeadPosition(self._head_position.x, self._head_position.y, z)
+ self._controller.setHeadPosition(self, self._head_position.x, self._head_position.y, z, speed)
+
+ @pyqtSlot(float, float, float)
+ @pyqtSlot(float, float, float, float)
+ def moveHead(self, x: float = 0, y: float = 0, z: float = 0, speed: float = 3000) -> None:
+ self._controller.moveHead(self, x, y, z, speed)
+
+ ## Pre-heats the heated bed of the printer.
+ #
+ # \param temperature The temperature to heat the bed to, in degrees
+ # Celsius.
+ # \param duration How long the bed should stay warm, in seconds.
+ @pyqtSlot(float, float)
+ def preheatBed(self, temperature: float, duration: float) -> None:
+ self._controller.preheatBed(self, temperature, duration)
+
+ @pyqtSlot()
+ def cancelPreheatBed(self) -> None:
+ self._controller.cancelPreheatBed(self)
+
+ def getController(self) -> "PrinterOutputController":
+ return self._controller
+
+ @pyqtProperty(str, notify = nameChanged)
+ def name(self) -> str:
+ return self._name
+
+ def setName(self, name: str) -> None:
+ self.updateName(name)
+
+ def updateName(self, name: str) -> None:
+ if self._name != name:
+ self._name = name
+ self.nameChanged.emit()
+
+ @pyqtProperty(str, notify = nameChanged)
+ def uniqueName(self) -> str:
+ return self._unique_name
+
+ def updateUniqueName(self, unique_name: str) -> None:
+ if self._unique_name != unique_name:
+ self._unique_name = unique_name
+ self.nameChanged.emit()
+
+ ## Update the bed temperature. This only changes it locally.
+ def updateBedTemperature(self, temperature: float) -> None:
+ if self._bed_temperature != temperature:
+ self._bed_temperature = temperature
+ self.bedTemperatureChanged.emit()
+
+ def updateTargetBedTemperature(self, temperature: float) -> None:
+ if self._target_bed_temperature != temperature:
+ self._target_bed_temperature = temperature
+ self.targetBedTemperatureChanged.emit()
+
+ ## Set the target bed temperature. This ensures that it's actually sent to the remote.
+ @pyqtSlot(float)
+ def setTargetBedTemperature(self, temperature: float) -> None:
+ self._controller.setTargetBedTemperature(self, temperature)
+ self.updateTargetBedTemperature(temperature)
+
+ def updateActivePrintJob(self, print_job: Optional["PrintJobOutputModel"]) -> None:
+ if self._active_print_job != print_job:
+ old_print_job = self._active_print_job
+
+ if print_job is not None:
+ print_job.updateAssignedPrinter(self)
+ self._active_print_job = print_job
+
+ if old_print_job is not None:
+ old_print_job.updateAssignedPrinter(None)
+ self.activePrintJobChanged.emit()
+
+ def updateState(self, printer_state: str) -> None:
+ if self._printer_state != printer_state:
+ self._printer_state = printer_state
+ self.stateChanged.emit()
+
+ @pyqtProperty(QObject, notify = activePrintJobChanged)
+ def activePrintJob(self) -> Optional["PrintJobOutputModel"]:
+ return self._active_print_job
+
+ @pyqtProperty(str, notify = stateChanged)
+ def state(self) -> str:
+ return self._printer_state
+
+ @pyqtProperty(float, notify = bedTemperatureChanged)
+ def bedTemperature(self) -> float:
+ return self._bed_temperature
+
+ @pyqtProperty(float, notify = targetBedTemperatureChanged)
+ def targetBedTemperature(self) -> float:
+ return self._target_bed_temperature
+
+ # Does the printer support pre-heating the bed at all
+ @pyqtProperty(bool, constant = True)
+ def canPreHeatBed(self) -> bool:
+ if self._controller:
+ return self._controller.can_pre_heat_bed
+ return False
+
+ # Does the printer support pre-heating the bed at all
+ @pyqtProperty(bool, constant = True)
+ def canPreHeatHotends(self) -> bool:
+ if self._controller:
+ return self._controller.can_pre_heat_hotends
+ return False
+
+ # Does the printer support sending raw G-code at all
+ @pyqtProperty(bool, constant = True)
+ def canSendRawGcode(self) -> bool:
+ if self._controller:
+ return self._controller.can_send_raw_gcode
+ return False
+
+ # Does the printer support pause at all
+ @pyqtProperty(bool, constant = True)
+ def canPause(self) -> bool:
+ if self._controller:
+ return self._controller.can_pause
+ return False
+
+ # Does the printer support abort at all
+ @pyqtProperty(bool, constant = True)
+ def canAbort(self) -> bool:
+ if self._controller:
+ return self._controller.can_abort
+ return False
+
+ # Does the printer support manual control at all
+ @pyqtProperty(bool, constant = True)
+ def canControlManually(self) -> bool:
+ if self._controller:
+ return self._controller.can_control_manually
+ return False
+
+ # Does the printer support upgrading firmware
+ @pyqtProperty(bool, notify = canUpdateFirmwareChanged)
+ def canUpdateFirmware(self) -> bool:
+ if self._controller:
+ return self._controller.can_update_firmware
+ return False
+
+ # Stub to connect UM.Signal to pyqtSignal
+ def _onControllerCanUpdateFirmwareChanged(self) -> None:
+ self.canUpdateFirmwareChanged.emit()
+
+ # Returns the active configuration (material, variant and buildplate) of the current printer
+ @pyqtProperty(QObject, notify = configurationChanged)
+ def printerConfiguration(self) -> Optional[PrinterConfigurationModel]:
+ if self._active_printer_configuration.isValid():
+ return self._active_printer_configuration
+ return None
+
+ peripheralsChanged = pyqtSignal()
+
+ @pyqtProperty(str, notify = peripheralsChanged)
+ def peripherals(self) -> str:
+ return ", ".join([peripheral.name for peripheral in self._peripherals])
+
+ def addPeripheral(self, peripheral: Peripheral) -> None:
+ self._peripherals.append(peripheral)
+ self.peripheralsChanged.emit()
+
+ def removePeripheral(self, peripheral: Peripheral) -> None:
+ self._peripherals.remove(peripheral)
+ self.peripheralsChanged.emit()
+
+ availableConfigurationsChanged = pyqtSignal()
+
+ # The availableConfigurations are configuration options that a printer can switch to, but doesn't currently have
+ # active (eg; Automatic tool changes, material loaders, etc).
+ @pyqtProperty("QVariantList", notify = availableConfigurationsChanged)
+ def availableConfigurations(self) -> List[PrinterConfigurationModel]:
+ return self._available_printer_configurations
+
+ def addAvailableConfiguration(self, new_configuration: PrinterConfigurationModel) -> None:
+ if new_configuration not in self._available_printer_configurations:
+ self._available_printer_configurations.append(new_configuration)
+ self.availableConfigurationsChanged.emit()
+
+ def removeAvailableConfiguration(self, config_to_remove: PrinterConfigurationModel) -> None:
+ try:
+ self._available_printer_configurations.remove(config_to_remove)
+ except ValueError:
+ Logger.log("w", "Unable to remove configuration that isn't in the list of available configurations")
+ else:
+ self.availableConfigurationsChanged.emit()
+
+ def setAvailableConfigurations(self, new_configurations: List[PrinterConfigurationModel]) -> None:
+ self._available_printer_configurations = new_configurations
+ self.availableConfigurationsChanged.emit()
diff --git a/cura/PrinterOutput/Models/__init__.py b/cura/PrinterOutput/Models/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
index 0e33a71249..60be5bc8f3 100644
--- a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
+++ b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
@@ -7,7 +7,7 @@ from UM.Scene.SceneNode import SceneNode #For typing.
from cura.API import Account
from cura.CuraApplication import CuraApplication
-from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply, QAuthenticator
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl, QCoreApplication
@@ -18,6 +18,8 @@ from enum import IntEnum
import os # To get the username
import gzip
+from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
+
class AuthState(IntEnum):
NotAuthenticated = 1
@@ -33,8 +35,6 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], connection_type: ConnectionType = ConnectionType.NetworkConnection, parent: QObject = None) -> None:
super().__init__(device_id = device_id, connection_type = connection_type, parent = parent)
self._manager = None # type: Optional[QNetworkAccessManager]
- self._last_manager_create_time = None # type: Optional[float]
- self._recreate_network_manager_time = 30
self._timeout_time = 10 # After how many seconds of no response should a timeout occur?
self._last_response_time = None # type: Optional[float]
@@ -58,8 +58,8 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self._gcode = [] # type: List[str]
self._connection_state_before_timeout = None # type: Optional[ConnectionState]
- def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
- file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
+ def requestWrite(self, nodes: List["SceneNode"], file_name: Optional[str] = None, limit_mimetypes: bool = False,
+ file_handler: Optional["FileHandler"] = None, filter_by_machine: bool = False, **kwargs) -> None:
raise NotImplementedError("requestWrite needs to be implemented")
def setAuthenticationState(self, authentication_state: AuthState) -> None:
@@ -131,12 +131,6 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self.setConnectionState(ConnectionState.Closed)
- # We need to check if the manager needs to be re-created. If we don't, we get some issues when OSX goes to
- # sleep.
- if time_since_last_response > self._recreate_network_manager_time:
- if self._last_manager_create_time is None or time() - self._last_manager_create_time > self._recreate_network_manager_time:
- self._createNetworkManager()
- assert(self._manager is not None)
elif self._connection_state == ConnectionState.Closed:
# Go out of timeout.
if self._connection_state_before_timeout is not None: # sanity check, but it should never be None here
@@ -160,7 +154,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
part = QHttpPart()
if not content_header.startswith("form-data;"):
- content_header = "form_data; " + content_header
+ content_header = "form-data; " + content_header
part.setHeader(QNetworkRequest.ContentDispositionHeader, content_header)
if content_type is not None:
@@ -315,16 +309,30 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self._manager = QNetworkAccessManager()
self._manager.finished.connect(self._handleOnFinished)
- self._last_manager_create_time = time()
self._manager.authenticationRequired.connect(self._onAuthenticationRequired)
if self._properties.get(b"temporary", b"false") != b"true":
- CuraApplication.getInstance().getMachineManager().checkCorrectGroupName(self.getId(), self.name)
+ self._checkCorrectGroupName(self.getId(), self.name)
def _registerOnFinishedCallback(self, reply: QNetworkReply, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
if on_finished is not None:
self._onFinishedCallbacks[reply.url().toString() + str(reply.operation())] = on_finished
+ ## This method checks if the name of the group stored in the definition container is correct.
+ # After updating from 3.2 to 3.3 some group names may be temporary. If there is a mismatch in the name of the group
+ # then all the container stacks are updated, both the current and the hidden ones.
+ def _checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
+ global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
+ active_machine_network_name = CuraApplication.getInstance().getMachineManager().activeMachineNetworkKey()
+ if global_container_stack and device_id == active_machine_network_name:
+ # Check if the group_name is correct. If not, update all the containers connected to the same printer
+ if CuraApplication.getInstance().getMachineManager().activeMachineNetworkGroupName != group_name:
+ metadata_filter = {"um_network_key": active_machine_network_name}
+ containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine",
+ **metadata_filter)
+ for container in containers:
+ container.setMetaDataEntry("group_name", group_name)
+
def _handleOnFinished(self, reply: QNetworkReply) -> None:
# Due to garbage collection, we need to cache certain bits of post operations.
# As we don't want to keep them around forever, delete them if we get a reply.
diff --git a/cura/PrinterOutput/Peripheral.py b/cura/PrinterOutput/Peripheral.py
new file mode 100644
index 0000000000..2693b82c36
--- /dev/null
+++ b/cura/PrinterOutput/Peripheral.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+
+## Data class that represents a peripheral for a printer.
+#
+# Output device plug-ins may specify that the printer has a certain set of
+# peripherals. This set is then possibly shown in the interface of the monitor
+# stage.
+class Peripheral:
+ ## Constructs the peripheral.
+ # \param type A unique ID for the type of peripheral.
+ # \param name A human-readable name for the peripheral.
+ def __init__(self, peripheral_type: str, name: str) -> None:
+ self.type = peripheral_type
+ self.name = name
diff --git a/cura/PrinterOutput/PrintJobOutputModel.py b/cura/PrinterOutput/PrintJobOutputModel.py
index fb163ef065..df66412df3 100644
--- a/cura/PrinterOutput/PrintJobOutputModel.py
+++ b/cura/PrinterOutput/PrintJobOutputModel.py
@@ -1,172 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
-from typing import Optional, TYPE_CHECKING, List
-
-from PyQt5.QtCore import QUrl
-from PyQt5.QtGui import QImage
-
-if TYPE_CHECKING:
- from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
- from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-
-
-class PrintJobOutputModel(QObject):
- stateChanged = pyqtSignal()
- timeTotalChanged = pyqtSignal()
- timeElapsedChanged = pyqtSignal()
- nameChanged = pyqtSignal()
- keyChanged = pyqtSignal()
- assignedPrinterChanged = pyqtSignal()
- ownerChanged = pyqtSignal()
- configurationChanged = pyqtSignal()
- previewImageChanged = pyqtSignal()
- compatibleMachineFamiliesChanged = pyqtSignal()
-
- def __init__(self, output_controller: "PrinterOutputController", key: str = "", name: str = "", parent=None) -> None:
- super().__init__(parent)
- self._output_controller = output_controller
- self._state = ""
- self._time_total = 0
- self._time_elapsed = 0
- self._name = name # Human readable name
- self._key = key # Unique identifier
- self._assigned_printer = None # type: Optional[PrinterOutputModel]
- self._owner = "" # Who started/owns the print job?
-
- self._configuration = None # type: Optional[ConfigurationModel]
- self._compatible_machine_families = [] # type: List[str]
- self._preview_image_id = 0
-
- self._preview_image = None # type: Optional[QImage]
-
- @pyqtProperty("QStringList", notify=compatibleMachineFamiliesChanged)
- def compatibleMachineFamilies(self):
- # Hack; Some versions of cluster will return a family more than once...
- return list(set(self._compatible_machine_families))
-
- def setCompatibleMachineFamilies(self, compatible_machine_families: List[str]) -> None:
- if self._compatible_machine_families != compatible_machine_families:
- self._compatible_machine_families = compatible_machine_families
- self.compatibleMachineFamiliesChanged.emit()
-
- @pyqtProperty(QUrl, notify=previewImageChanged)
- def previewImageUrl(self):
- self._preview_image_id += 1
- # There is an image provider that is called "print_job_preview". In order to ensure that the image qml object, that
- # requires a QUrl to function, updates correctly we add an increasing number. This causes to see the QUrl
- # as new (instead of relying on cached version and thus forces an update.
- temp = "image://print_job_preview/" + str(self._preview_image_id) + "/" + self._key
- return QUrl(temp, QUrl.TolerantMode)
-
- def getPreviewImage(self) -> Optional[QImage]:
- return self._preview_image
-
- def updatePreviewImage(self, preview_image: Optional[QImage]) -> None:
- if self._preview_image != preview_image:
- self._preview_image = preview_image
- self.previewImageChanged.emit()
-
- @pyqtProperty(QObject, notify=configurationChanged)
- def configuration(self) -> Optional["ConfigurationModel"]:
- return self._configuration
-
- def updateConfiguration(self, configuration: Optional["ConfigurationModel"]) -> None:
- if self._configuration != configuration:
- self._configuration = configuration
- self.configurationChanged.emit()
-
- @pyqtProperty(str, notify=ownerChanged)
- def owner(self):
- return self._owner
-
- def updateOwner(self, owner):
- if self._owner != owner:
- self._owner = owner
- self.ownerChanged.emit()
-
- @pyqtProperty(QObject, notify=assignedPrinterChanged)
- def assignedPrinter(self):
- return self._assigned_printer
-
- def updateAssignedPrinter(self, assigned_printer: Optional["PrinterOutputModel"]) -> None:
- if self._assigned_printer != assigned_printer:
- old_printer = self._assigned_printer
- self._assigned_printer = assigned_printer
- if old_printer is not None:
- # If the previously assigned printer is set, this job is moved away from it.
- old_printer.updateActivePrintJob(None)
- self.assignedPrinterChanged.emit()
-
- @pyqtProperty(str, notify=keyChanged)
- def key(self):
- return self._key
-
- def updateKey(self, key: str):
- if self._key != key:
- self._key = key
- self.keyChanged.emit()
-
- @pyqtProperty(str, notify = nameChanged)
- def name(self):
- return self._name
-
- def updateName(self, name: str):
- if self._name != name:
- self._name = name
- self.nameChanged.emit()
-
- @pyqtProperty(int, notify = timeTotalChanged)
- def timeTotal(self) -> int:
- return self._time_total
-
- @pyqtProperty(int, notify = timeElapsedChanged)
- def timeElapsed(self) -> int:
- return self._time_elapsed
-
- @pyqtProperty(int, notify = timeElapsedChanged)
- def timeRemaining(self) -> int:
- # Never get a negative time remaining
- return max(self.timeTotal - self.timeElapsed, 0)
-
- @pyqtProperty(float, notify = timeElapsedChanged)
- def progress(self) -> float:
- result = float(self.timeElapsed) / max(self.timeTotal, 1.0) # Prevent a division by zero exception.
- return min(result, 1.0) # Never get a progress past 1.0
-
- @pyqtProperty(str, notify=stateChanged)
- def state(self) -> str:
- return self._state
-
- @pyqtProperty(bool, notify=stateChanged)
- def isActive(self) -> bool:
- inactiveStates = [
- "pausing",
- "paused",
- "resuming",
- "wait_cleanup"
- ]
- if self.state in inactiveStates and self.timeRemaining > 0:
- return False
- return True
-
- def updateTimeTotal(self, new_time_total):
- if self._time_total != new_time_total:
- self._time_total = new_time_total
- self.timeTotalChanged.emit()
-
- def updateTimeElapsed(self, new_time_elapsed):
- if self._time_elapsed != new_time_elapsed:
- self._time_elapsed = new_time_elapsed
- self.timeElapsedChanged.emit()
-
- def updateState(self, new_state):
- if self._state != new_state:
- self._state = new_state
- self.stateChanged.emit()
-
- @pyqtSlot(str)
- def setState(self, state):
- self._output_controller.setJobState(self, state)
+import warnings
+warnings.warn("Importing cura.PrinterOutput.PrintJobOutputModel has been deprecated since 4.1, use cura.PrinterOutput.Models.PrintJobOutputModel instead", DeprecationWarning, stacklevel=2)
+# We moved the the models to one submodule deeper
+from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
\ No newline at end of file
diff --git a/cura/PrinterOutput/PrinterOutputController.py b/cura/PrinterOutput/PrinterOutputController.py
index aa06ada8a3..3d710582ca 100644
--- a/cura/PrinterOutput/PrinterOutputController.py
+++ b/cura/PrinterOutput/PrinterOutputController.py
@@ -4,14 +4,12 @@
from UM.Logger import Logger
from UM.Signal import Signal
-from typing import Union
-
MYPY = False
if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
- from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+ from .Models.PrintJobOutputModel import PrintJobOutputModel
+ from .Models.ExtruderOutputModel import ExtruderOutputModel
+ from .Models.PrinterOutputModel import PrinterOutputModel
+ from .PrinterOutputDevice import PrinterOutputDevice
class PrinterOutputController:
diff --git a/cura/PrinterOutput/PrinterOutputDevice.py b/cura/PrinterOutput/PrinterOutputDevice.py
new file mode 100644
index 0000000000..b05e76ad2e
--- /dev/null
+++ b/cura/PrinterOutput/PrinterOutputDevice.py
@@ -0,0 +1,264 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from enum import IntEnum
+from typing import Callable, List, Optional, Union
+
+from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTimer, QUrl
+from PyQt5.QtWidgets import QMessageBox
+
+from UM.Logger import Logger
+from UM.Signal import signalemitter
+from UM.Qt.QtApplication import QtApplication
+from UM.FlameProfiler import pyqtSlot
+from UM.i18n import i18nCatalog
+from UM.OutputDevice.OutputDevice import OutputDevice
+
+MYPY = False
+if MYPY:
+ from UM.FileHandler.FileHandler import FileHandler
+ from UM.Scene.SceneNode import SceneNode
+ from .Models.PrinterOutputModel import PrinterOutputModel
+ from .Models.PrinterConfigurationModel import PrinterConfigurationModel
+ from .FirmwareUpdater import FirmwareUpdater
+
+i18n_catalog = i18nCatalog("cura")
+
+
+## The current processing state of the backend.
+class ConnectionState(IntEnum):
+ Closed = 0
+ Connecting = 1
+ Connected = 2
+ Busy = 3
+ Error = 4
+
+
+class ConnectionType(IntEnum):
+ NotConnected = 0
+ UsbConnection = 1
+ NetworkConnection = 2
+ CloudConnection = 3
+
+
+## Printer output device adds extra interface options on top of output device.
+#
+# The assumption is made the printer is a FDM printer.
+#
+# Note that a number of settings are marked as "final". This is because decorators
+# are not inherited by children. To fix this we use the private counter part of those
+# functions to actually have the implementation.
+#
+# For all other uses it should be used in the same way as a "regular" OutputDevice.
+@signalemitter
+class PrinterOutputDevice(QObject, OutputDevice):
+
+ printersChanged = pyqtSignal()
+ connectionStateChanged = pyqtSignal(str)
+ acceptsCommandsChanged = pyqtSignal()
+
+ # Signal to indicate that the material of the active printer on the remote changed.
+ materialIdChanged = pyqtSignal()
+
+ # # Signal to indicate that the hotend of the active printer on the remote changed.
+ hotendIdChanged = pyqtSignal()
+
+ # Signal to indicate that the info text about the connection has changed.
+ connectionTextChanged = pyqtSignal()
+
+ # Signal to indicate that the configuration of one of the printers has changed.
+ uniqueConfigurationsChanged = pyqtSignal()
+
+ def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.NotConnected, parent: QObject = None) -> None:
+ super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance
+
+ self._printers = [] # type: List[PrinterOutputModel]
+ self._unique_configurations = [] # type: List[PrinterConfigurationModel]
+
+ self._monitor_view_qml_path = "" # type: str
+ self._monitor_component = None # type: Optional[QObject]
+ self._monitor_item = None # type: Optional[QObject]
+
+ self._control_view_qml_path = "" # type: str
+ self._control_component = None # type: Optional[QObject]
+ self._control_item = None # type: Optional[QObject]
+
+ self._accepts_commands = False # type: bool
+
+ self._update_timer = QTimer() # type: QTimer
+ self._update_timer.setInterval(2000) # TODO; Add preference for update interval
+ self._update_timer.setSingleShot(False)
+ self._update_timer.timeout.connect(self._update)
+
+ self._connection_state = ConnectionState.Closed # type: ConnectionState
+ self._connection_type = connection_type # type: ConnectionType
+
+ self._firmware_updater = None # type: Optional[FirmwareUpdater]
+ self._firmware_name = None # type: Optional[str]
+ self._address = "" # type: str
+ self._connection_text = "" # type: str
+ self.printersChanged.connect(self._onPrintersChanged)
+ QtApplication.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._updateUniqueConfigurations)
+
+ @pyqtProperty(str, notify = connectionTextChanged)
+ def address(self) -> str:
+ return self._address
+
+ def setConnectionText(self, connection_text):
+ if self._connection_text != connection_text:
+ self._connection_text = connection_text
+ self.connectionTextChanged.emit()
+
+ @pyqtProperty(str, constant=True)
+ def connectionText(self) -> str:
+ return self._connection_text
+
+ def materialHotendChangedMessage(self, callback: Callable[[int], None]) -> None:
+ Logger.log("w", "materialHotendChangedMessage needs to be implemented, returning 'Yes'")
+ callback(QMessageBox.Yes)
+
+ def isConnected(self) -> bool:
+ return self._connection_state != ConnectionState.Closed and self._connection_state != ConnectionState.Error
+
+ def setConnectionState(self, connection_state: "ConnectionState") -> None:
+ if self._connection_state != connection_state:
+ self._connection_state = connection_state
+ self.connectionStateChanged.emit(self._id)
+
+ @pyqtProperty(int, constant = True)
+ def connectionType(self) -> "ConnectionType":
+ return self._connection_type
+
+ @pyqtProperty(int, notify = connectionStateChanged)
+ def connectionState(self) -> "ConnectionState":
+ return self._connection_state
+
+ def _update(self) -> None:
+ pass
+
+ def _getPrinterByKey(self, key: str) -> Optional["PrinterOutputModel"]:
+ for printer in self._printers:
+ if printer.key == key:
+ return printer
+
+ return None
+
+ def requestWrite(self, nodes: List["SceneNode"], file_name: Optional[str] = None, limit_mimetypes: bool = False,
+ file_handler: Optional["FileHandler"] = None, filter_by_machine: bool = False, **kwargs) -> None:
+ raise NotImplementedError("requestWrite needs to be implemented")
+
+ @pyqtProperty(QObject, notify = printersChanged)
+ def activePrinter(self) -> Optional["PrinterOutputModel"]:
+ if len(self._printers):
+ return self._printers[0]
+ return None
+
+ @pyqtProperty("QVariantList", notify = printersChanged)
+ def printers(self) -> List["PrinterOutputModel"]:
+ return self._printers
+
+ @pyqtProperty(QObject, constant = True)
+ def monitorItem(self) -> QObject:
+ # Note that we specifically only check if the monitor component is created.
+ # It could be that it failed to actually create the qml item! If we check if the item was created, it will try to
+ # create the item (and fail) every time.
+ if not self._monitor_component:
+ self._createMonitorViewFromQML()
+ return self._monitor_item
+
+ @pyqtProperty(QObject, constant = True)
+ def controlItem(self) -> QObject:
+ if not self._control_component:
+ self._createControlViewFromQML()
+ return self._control_item
+
+ def _createControlViewFromQML(self) -> None:
+ if not self._control_view_qml_path:
+ return
+ if self._control_item is None:
+ self._control_item = QtApplication.getInstance().createQmlComponent(self._control_view_qml_path, {"OutputDevice": self})
+
+ def _createMonitorViewFromQML(self) -> None:
+ if not self._monitor_view_qml_path:
+ return
+
+ if self._monitor_item is None:
+ self._monitor_item = QtApplication.getInstance().createQmlComponent(self._monitor_view_qml_path, {"OutputDevice": self})
+
+ ## Attempt to establish connection
+ def connect(self) -> None:
+ self.setConnectionState(ConnectionState.Connecting)
+ self._update_timer.start()
+
+ ## Attempt to close the connection
+ def close(self) -> None:
+ self._update_timer.stop()
+ self.setConnectionState(ConnectionState.Closed)
+
+ ## Ensure that close gets called when object is destroyed
+ def __del__(self) -> None:
+ self.close()
+
+ @pyqtProperty(bool, notify = acceptsCommandsChanged)
+ def acceptsCommands(self) -> bool:
+ return self._accepts_commands
+
+ ## Set a flag to signal the UI that the printer is not (yet) ready to receive commands
+ def _setAcceptsCommands(self, accepts_commands: bool) -> None:
+ if self._accepts_commands != accepts_commands:
+ self._accepts_commands = accepts_commands
+
+ self.acceptsCommandsChanged.emit()
+
+ # Returns the unique configurations of the printers within this output device
+ @pyqtProperty("QVariantList", notify = uniqueConfigurationsChanged)
+ def uniqueConfigurations(self) -> List["PrinterConfigurationModel"]:
+ return self._unique_configurations
+
+ def _updateUniqueConfigurations(self) -> None:
+ all_configurations = set()
+ for printer in self._printers:
+ if printer.printerConfiguration is not None and printer.printerConfiguration.hasAnyMaterialLoaded():
+ all_configurations.add(printer.printerConfiguration)
+ all_configurations.update(printer.availableConfigurations)
+ if None in all_configurations: # Shouldn't happen, but it does. I don't see how it could ever happen. Skip adding that configuration. List could end up empty!
+ Logger.log("e", "Found a broken configuration in the synced list!")
+ all_configurations.remove(None)
+ new_configurations = sorted(all_configurations, key = lambda config: config.printerType or "")
+ if new_configurations != self._unique_configurations:
+ self._unique_configurations = new_configurations
+ self.uniqueConfigurationsChanged.emit()
+
+ # Returns the unique configurations of the printers within this output device
+ @pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
+ def uniquePrinterTypes(self) -> List[str]:
+ return list(sorted(set([configuration.printerType or "" for configuration in self._unique_configurations])))
+
+ def _onPrintersChanged(self) -> None:
+ for printer in self._printers:
+ printer.configurationChanged.connect(self._updateUniqueConfigurations)
+ printer.availableConfigurationsChanged.connect(self._updateUniqueConfigurations)
+
+ # At this point there may be non-updated configurations
+ self._updateUniqueConfigurations()
+
+ ## Set the device firmware name
+ #
+ # \param name The name of the firmware.
+ def _setFirmwareName(self, name: str) -> None:
+ self._firmware_name = name
+
+ ## Get the name of device firmware
+ #
+ # This name can be used to define device type
+ def getFirmwareName(self) -> Optional[str]:
+ return self._firmware_name
+
+ def getFirmwareUpdater(self) -> Optional["FirmwareUpdater"]:
+ return self._firmware_updater
+
+ @pyqtSlot(str)
+ def updateFirmware(self, firmware_file: Union[str, QUrl]) -> None:
+ if not self._firmware_updater:
+ return
+
+ self._firmware_updater.updateFirmware(firmware_file)
diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py
index 12884b5f9b..87020ce2d0 100644
--- a/cura/PrinterOutput/PrinterOutputModel.py
+++ b/cura/PrinterOutput/PrinterOutputModel.py
@@ -1,297 +1,4 @@
-# Copyright (c) 2019 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot, QUrl
-from typing import List, Dict, Optional
-from UM.Math.Vector import Vector
-from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
-
-MYPY = False
-if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
-
-
-class PrinterOutputModel(QObject):
- bedTemperatureChanged = pyqtSignal()
- targetBedTemperatureChanged = pyqtSignal()
- isPreheatingChanged = pyqtSignal()
- stateChanged = pyqtSignal()
- activePrintJobChanged = pyqtSignal()
- nameChanged = pyqtSignal()
- headPositionChanged = pyqtSignal()
- keyChanged = pyqtSignal()
- typeChanged = pyqtSignal()
- buildplateChanged = pyqtSignal()
- cameraUrlChanged = pyqtSignal()
- configurationChanged = pyqtSignal()
- canUpdateFirmwareChanged = pyqtSignal()
-
- def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = "") -> None:
- super().__init__(parent)
- self._bed_temperature = -1 # type: float # Use -1 for no heated bed.
- self._target_bed_temperature = 0 # type: float
- self._name = ""
- self._key = "" # Unique identifier
- self._controller = output_controller
- self._controller.canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
- self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
- self._printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
- self._head_position = Vector(0, 0, 0)
- self._active_print_job = None # type: Optional[PrintJobOutputModel]
- self._firmware_version = firmware_version
- self._printer_state = "unknown"
- self._is_preheating = False
- self._printer_type = ""
- self._buildplate = ""
-
- self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
- self._extruders]
-
- self._camera_url = QUrl() # type: QUrl
-
- @pyqtProperty(str, constant = True)
- def firmwareVersion(self) -> str:
- return self._firmware_version
-
- def setCameraUrl(self, camera_url: "QUrl") -> None:
- if self._camera_url != camera_url:
- self._camera_url = camera_url
- self.cameraUrlChanged.emit()
-
- @pyqtProperty(QUrl, fset = setCameraUrl, notify = cameraUrlChanged)
- def cameraUrl(self) -> "QUrl":
- return self._camera_url
-
- def updateIsPreheating(self, pre_heating: bool) -> None:
- if self._is_preheating != pre_heating:
- self._is_preheating = pre_heating
- self.isPreheatingChanged.emit()
-
- @pyqtProperty(bool, notify=isPreheatingChanged)
- def isPreheating(self) -> bool:
- return self._is_preheating
-
- @pyqtProperty(str, notify = typeChanged)
- def type(self) -> str:
- return self._printer_type
-
- def updateType(self, printer_type: str) -> None:
- if self._printer_type != printer_type:
- self._printer_type = printer_type
- self._printer_configuration.printerType = self._printer_type
- self.typeChanged.emit()
- self.configurationChanged.emit()
-
- @pyqtProperty(str, notify = buildplateChanged)
- def buildplate(self) -> str:
- return self._buildplate
-
- def updateBuildplate(self, buildplate: str) -> None:
- if self._buildplate != buildplate:
- self._buildplate = buildplate
- self._printer_configuration.buildplateConfiguration = self._buildplate
- self.buildplateChanged.emit()
- self.configurationChanged.emit()
-
- @pyqtProperty(str, notify=keyChanged)
- def key(self) -> str:
- return self._key
-
- def updateKey(self, key: str) -> None:
- if self._key != key:
- self._key = key
- self.keyChanged.emit()
-
- @pyqtSlot()
- def homeHead(self) -> None:
- self._controller.homeHead(self)
-
- @pyqtSlot()
- def homeBed(self) -> None:
- self._controller.homeBed(self)
-
- @pyqtSlot(str)
- def sendRawCommand(self, command: str) -> None:
- self._controller.sendRawCommand(self, command)
-
- @pyqtProperty("QVariantList", constant = True)
- def extruders(self) -> List["ExtruderOutputModel"]:
- return self._extruders
-
- @pyqtProperty(QVariant, notify = headPositionChanged)
- def headPosition(self) -> Dict[str, float]:
- return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z}
-
- def updateHeadPosition(self, x: float, y: float, z: float) -> None:
- if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z:
- self._head_position = Vector(x, y, z)
- self.headPositionChanged.emit()
-
- @pyqtProperty(float, float, float)
- @pyqtProperty(float, float, float, float)
- def setHeadPosition(self, x: float, y: float, z: float, speed: float = 3000) -> None:
- self.updateHeadPosition(x, y, z)
- self._controller.setHeadPosition(self, x, y, z, speed)
-
- @pyqtProperty(float)
- @pyqtProperty(float, float)
- def setHeadX(self, x: float, speed: float = 3000) -> None:
- self.updateHeadPosition(x, self._head_position.y, self._head_position.z)
- self._controller.setHeadPosition(self, x, self._head_position.y, self._head_position.z, speed)
-
- @pyqtProperty(float)
- @pyqtProperty(float, float)
- def setHeadY(self, y: float, speed: float = 3000) -> None:
- self.updateHeadPosition(self._head_position.x, y, self._head_position.z)
- self._controller.setHeadPosition(self, self._head_position.x, y, self._head_position.z, speed)
-
- @pyqtProperty(float)
- @pyqtProperty(float, float)
- def setHeadZ(self, z: float, speed:float = 3000) -> None:
- self.updateHeadPosition(self._head_position.x, self._head_position.y, z)
- self._controller.setHeadPosition(self, self._head_position.x, self._head_position.y, z, speed)
-
- @pyqtSlot(float, float, float)
- @pyqtSlot(float, float, float, float)
- def moveHead(self, x: float = 0, y: float = 0, z: float = 0, speed: float = 3000) -> None:
- self._controller.moveHead(self, x, y, z, speed)
-
- ## Pre-heats the heated bed of the printer.
- #
- # \param temperature The temperature to heat the bed to, in degrees
- # Celsius.
- # \param duration How long the bed should stay warm, in seconds.
- @pyqtSlot(float, float)
- def preheatBed(self, temperature: float, duration: float) -> None:
- self._controller.preheatBed(self, temperature, duration)
-
- @pyqtSlot()
- def cancelPreheatBed(self) -> None:
- self._controller.cancelPreheatBed(self)
-
- def getController(self) -> "PrinterOutputController":
- return self._controller
-
- @pyqtProperty(str, notify = nameChanged)
- def name(self) -> str:
- return self._name
-
- def setName(self, name: str) -> None:
- self.updateName(name)
-
- def updateName(self, name: str) -> None:
- if self._name != name:
- self._name = name
- self.nameChanged.emit()
-
- ## Update the bed temperature. This only changes it locally.
- def updateBedTemperature(self, temperature: float) -> None:
- if self._bed_temperature != temperature:
- self._bed_temperature = temperature
- self.bedTemperatureChanged.emit()
-
- def updateTargetBedTemperature(self, temperature: float) -> None:
- if self._target_bed_temperature != temperature:
- self._target_bed_temperature = temperature
- self.targetBedTemperatureChanged.emit()
-
- ## Set the target bed temperature. This ensures that it's actually sent to the remote.
- @pyqtSlot(float)
- def setTargetBedTemperature(self, temperature: float) -> None:
- self._controller.setTargetBedTemperature(self, temperature)
- self.updateTargetBedTemperature(temperature)
-
- def updateActivePrintJob(self, print_job: Optional["PrintJobOutputModel"]) -> None:
- if self._active_print_job != print_job:
- old_print_job = self._active_print_job
-
- if print_job is not None:
- print_job.updateAssignedPrinter(self)
- self._active_print_job = print_job
-
- if old_print_job is not None:
- old_print_job.updateAssignedPrinter(None)
- self.activePrintJobChanged.emit()
-
- def updateState(self, printer_state: str) -> None:
- if self._printer_state != printer_state:
- self._printer_state = printer_state
- self.stateChanged.emit()
-
- @pyqtProperty(QObject, notify = activePrintJobChanged)
- def activePrintJob(self) -> Optional["PrintJobOutputModel"]:
- return self._active_print_job
-
- @pyqtProperty(str, notify = stateChanged)
- def state(self) -> str:
- return self._printer_state
-
- @pyqtProperty(float, notify = bedTemperatureChanged)
- def bedTemperature(self) -> float:
- return self._bed_temperature
-
- @pyqtProperty(float, notify = targetBedTemperatureChanged)
- def targetBedTemperature(self) -> float:
- return self._target_bed_temperature
-
- # Does the printer support pre-heating the bed at all
- @pyqtProperty(bool, constant = True)
- def canPreHeatBed(self) -> bool:
- if self._controller:
- return self._controller.can_pre_heat_bed
- return False
-
- # Does the printer support pre-heating the bed at all
- @pyqtProperty(bool, constant = True)
- def canPreHeatHotends(self) -> bool:
- if self._controller:
- return self._controller.can_pre_heat_hotends
- return False
-
- # Does the printer support sending raw G-code at all
- @pyqtProperty(bool, constant = True)
- def canSendRawGcode(self) -> bool:
- if self._controller:
- return self._controller.can_send_raw_gcode
- return False
-
- # Does the printer support pause at all
- @pyqtProperty(bool, constant = True)
- def canPause(self) -> bool:
- if self._controller:
- return self._controller.can_pause
- return False
-
- # Does the printer support abort at all
- @pyqtProperty(bool, constant = True)
- def canAbort(self) -> bool:
- if self._controller:
- return self._controller.can_abort
- return False
-
- # Does the printer support manual control at all
- @pyqtProperty(bool, constant = True)
- def canControlManually(self) -> bool:
- if self._controller:
- return self._controller.can_control_manually
- return False
-
- # Does the printer support upgrading firmware
- @pyqtProperty(bool, notify = canUpdateFirmwareChanged)
- def canUpdateFirmware(self) -> bool:
- if self._controller:
- return self._controller.can_update_firmware
- return False
-
- # Stub to connect UM.Signal to pyqtSignal
- def _onControllerCanUpdateFirmwareChanged(self) -> None:
- self.canUpdateFirmwareChanged.emit()
-
- # Returns the configuration (material, variant and buildplate) of the current printer
- @pyqtProperty(QObject, notify = configurationChanged)
- def printerConfiguration(self) -> Optional[ConfigurationModel]:
- if self._printer_configuration.isValid():
- return self._printer_configuration
- return None
\ No newline at end of file
+import warnings
+warnings.warn("Importing cura.PrinterOutput.PrinterOutputModel has been deprecated since 4.1, use cura.PrinterOutput.Models.PrinterOutputModel instead", DeprecationWarning, stacklevel=2)
+# We moved the the models to one submodule deeper
+from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
\ No newline at end of file
diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py
index dbdf8c986c..51e563410c 100644
--- a/cura/PrinterOutputDevice.py
+++ b/cura/PrinterOutputDevice.py
@@ -1,261 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from enum import IntEnum
-from typing import Callable, List, Optional, Union
-
-from UM.Decorators import deprecated
-from UM.i18n import i18nCatalog
-from UM.OutputDevice.OutputDevice import OutputDevice
-from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTimer, QUrl
-from PyQt5.QtWidgets import QMessageBox
-
-from UM.Logger import Logger
-from UM.Signal import signalemitter
-from UM.Qt.QtApplication import QtApplication
-from UM.FlameProfiler import pyqtSlot
-
-MYPY = False
-if MYPY:
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
- from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
- from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater
- from UM.FileHandler.FileHandler import FileHandler
- from UM.Scene.SceneNode import SceneNode
-
-i18n_catalog = i18nCatalog("cura")
-
-
-## The current processing state of the backend.
-class ConnectionState(IntEnum):
- Closed = 0
- Connecting = 1
- Connected = 2
- Busy = 3
- Error = 4
-
-
-class ConnectionType(IntEnum):
- NotConnected = 0
- UsbConnection = 1
- NetworkConnection = 2
- CloudConnection = 3
-
-
-## Printer output device adds extra interface options on top of output device.
-#
-# The assumption is made the printer is a FDM printer.
-#
-# Note that a number of settings are marked as "final". This is because decorators
-# are not inherited by children. To fix this we use the private counter part of those
-# functions to actually have the implementation.
-#
-# For all other uses it should be used in the same way as a "regular" OutputDevice.
-@signalemitter
-class PrinterOutputDevice(QObject, OutputDevice):
-
- printersChanged = pyqtSignal()
- connectionStateChanged = pyqtSignal(str)
- acceptsCommandsChanged = pyqtSignal()
-
- # Signal to indicate that the material of the active printer on the remote changed.
- materialIdChanged = pyqtSignal()
-
- # # Signal to indicate that the hotend of the active printer on the remote changed.
- hotendIdChanged = pyqtSignal()
-
- # Signal to indicate that the info text about the connection has changed.
- connectionTextChanged = pyqtSignal()
-
- # Signal to indicate that the configuration of one of the printers has changed.
- uniqueConfigurationsChanged = pyqtSignal()
-
- def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.NotConnected, parent: QObject = None) -> None:
- super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance
-
- self._printers = [] # type: List[PrinterOutputModel]
- self._unique_configurations = [] # type: List[ConfigurationModel]
-
- self._monitor_view_qml_path = "" # type: str
- self._monitor_component = None # type: Optional[QObject]
- self._monitor_item = None # type: Optional[QObject]
-
- self._control_view_qml_path = "" # type: str
- self._control_component = None # type: Optional[QObject]
- self._control_item = None # type: Optional[QObject]
-
- self._accepts_commands = False # type: bool
-
- self._update_timer = QTimer() # type: QTimer
- self._update_timer.setInterval(2000) # TODO; Add preference for update interval
- self._update_timer.setSingleShot(False)
- self._update_timer.timeout.connect(self._update)
-
- self._connection_state = ConnectionState.Closed # type: ConnectionState
- self._connection_type = connection_type # type: ConnectionType
-
- self._firmware_updater = None # type: Optional[FirmwareUpdater]
- self._firmware_name = None # type: Optional[str]
- self._address = "" # type: str
- self._connection_text = "" # type: str
- self.printersChanged.connect(self._onPrintersChanged)
- QtApplication.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._updateUniqueConfigurations)
-
- @pyqtProperty(str, notify = connectionTextChanged)
- def address(self) -> str:
- return self._address
-
- def setConnectionText(self, connection_text):
- if self._connection_text != connection_text:
- self._connection_text = connection_text
- self.connectionTextChanged.emit()
-
- @pyqtProperty(str, constant=True)
- def connectionText(self) -> str:
- return self._connection_text
-
- def materialHotendChangedMessage(self, callback: Callable[[int], None]) -> None:
- Logger.log("w", "materialHotendChangedMessage needs to be implemented, returning 'Yes'")
- callback(QMessageBox.Yes)
-
- def isConnected(self) -> bool:
- return self._connection_state != ConnectionState.Closed and self._connection_state != ConnectionState.Error
-
- def setConnectionState(self, connection_state: "ConnectionState") -> None:
- if self._connection_state != connection_state:
- self._connection_state = connection_state
- self.connectionStateChanged.emit(self._id)
-
- @pyqtProperty(int, constant = True)
- def connectionType(self) -> "ConnectionType":
- return self._connection_type
-
- @pyqtProperty(int, notify = connectionStateChanged)
- def connectionState(self) -> "ConnectionState":
- return self._connection_state
-
- def _update(self) -> None:
- pass
-
- def _getPrinterByKey(self, key: str) -> Optional["PrinterOutputModel"]:
- for printer in self._printers:
- if printer.key == key:
- return printer
-
- return None
-
- def requestWrite(self, nodes: List["SceneNode"], file_name: Optional[str] = None, limit_mimetypes: bool = False,
- file_handler: Optional["FileHandler"] = None, **kwargs: str) -> None:
- raise NotImplementedError("requestWrite needs to be implemented")
-
- @pyqtProperty(QObject, notify = printersChanged)
- def activePrinter(self) -> Optional["PrinterOutputModel"]:
- if len(self._printers):
- return self._printers[0]
- return None
-
- @pyqtProperty("QVariantList", notify = printersChanged)
- def printers(self) -> List["PrinterOutputModel"]:
- return self._printers
-
- @pyqtProperty(QObject, constant = True)
- def monitorItem(self) -> QObject:
- # Note that we specifically only check if the monitor component is created.
- # It could be that it failed to actually create the qml item! If we check if the item was created, it will try to
- # create the item (and fail) every time.
- if not self._monitor_component:
- self._createMonitorViewFromQML()
- return self._monitor_item
-
- @pyqtProperty(QObject, constant = True)
- def controlItem(self) -> QObject:
- if not self._control_component:
- self._createControlViewFromQML()
- return self._control_item
-
- def _createControlViewFromQML(self) -> None:
- if not self._control_view_qml_path:
- return
- if self._control_item is None:
- self._control_item = QtApplication.getInstance().createQmlComponent(self._control_view_qml_path, {"OutputDevice": self})
-
- def _createMonitorViewFromQML(self) -> None:
- if not self._monitor_view_qml_path:
- return
-
- if self._monitor_item is None:
- self._monitor_item = QtApplication.getInstance().createQmlComponent(self._monitor_view_qml_path, {"OutputDevice": self})
-
- ## Attempt to establish connection
- def connect(self) -> None:
- self.setConnectionState(ConnectionState.Connecting)
- self._update_timer.start()
-
- ## Attempt to close the connection
- def close(self) -> None:
- self._update_timer.stop()
- self.setConnectionState(ConnectionState.Closed)
-
- ## Ensure that close gets called when object is destroyed
- def __del__(self) -> None:
- self.close()
-
- @pyqtProperty(bool, notify = acceptsCommandsChanged)
- def acceptsCommands(self) -> bool:
- return self._accepts_commands
-
- @deprecated("Please use the protected function instead", "3.2")
- def setAcceptsCommands(self, accepts_commands: bool) -> None:
- self._setAcceptsCommands(accepts_commands)
-
- ## Set a flag to signal the UI that the printer is not (yet) ready to receive commands
- def _setAcceptsCommands(self, accepts_commands: bool) -> None:
- if self._accepts_commands != accepts_commands:
- self._accepts_commands = accepts_commands
-
- self.acceptsCommandsChanged.emit()
-
- # Returns the unique configurations of the printers within this output device
- @pyqtProperty("QVariantList", notify = uniqueConfigurationsChanged)
- def uniqueConfigurations(self) -> List["ConfigurationModel"]:
- return self._unique_configurations
-
- def _updateUniqueConfigurations(self) -> None:
- self._unique_configurations = sorted(
- {printer.printerConfiguration for printer in self._printers if printer.printerConfiguration is not None},
- key=lambda config: config.printerType,
- )
- self.uniqueConfigurationsChanged.emit()
-
- # Returns the unique configurations of the printers within this output device
- @pyqtProperty("QStringList", notify = uniqueConfigurationsChanged)
- def uniquePrinterTypes(self) -> List[str]:
- return list(sorted(set([configuration.printerType for configuration in self._unique_configurations])))
-
- def _onPrintersChanged(self) -> None:
- for printer in self._printers:
- printer.configurationChanged.connect(self._updateUniqueConfigurations)
-
- # At this point there may be non-updated configurations
- self._updateUniqueConfigurations()
-
- ## Set the device firmware name
- #
- # \param name The name of the firmware.
- def _setFirmwareName(self, name: str) -> None:
- self._firmware_name = name
-
- ## Get the name of device firmware
- #
- # This name can be used to define device type
- def getFirmwareName(self) -> Optional[str]:
- return self._firmware_name
-
- def getFirmwareUpdater(self) -> Optional["FirmwareUpdater"]:
- return self._firmware_updater
-
- @pyqtSlot(str)
- def updateFirmware(self, firmware_file: Union[str, QUrl]) -> None:
- if not self._firmware_updater:
- return
-
- self._firmware_updater.updateFirmware(firmware_file)
+import warnings
+warnings.warn("Importing cura.PrinterOutputDevice has been deprecated since 4.1, use cura.PrinterOutput.PrinterOutputDevice instead", DeprecationWarning, stacklevel=2)
+# We moved the PrinterOutput device to it's own submodule.
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
\ No newline at end of file
diff --git a/cura/Scene/BuildPlateDecorator.py b/cura/Scene/BuildPlateDecorator.py
index dfb465b7ad..cff9f88f62 100644
--- a/cura/Scene/BuildPlateDecorator.py
+++ b/cura/Scene/BuildPlateDecorator.py
@@ -4,12 +4,12 @@ from cura.Scene.CuraSceneNode import CuraSceneNode
## Make a SceneNode build plate aware CuraSceneNode objects all have this decorator.
class BuildPlateDecorator(SceneNodeDecorator):
- def __init__(self, build_plate_number = -1):
+ def __init__(self, build_plate_number: int = -1) -> None:
super().__init__()
- self._build_plate_number = None
+ self._build_plate_number = build_plate_number
self.setBuildPlateNumber(build_plate_number)
- def setBuildPlateNumber(self, nr):
+ def setBuildPlateNumber(self, nr: int) -> None:
# Make sure that groups are set correctly
# setBuildPlateForSelection in CuraActions makes sure that no single childs are set.
self._build_plate_number = nr
@@ -19,7 +19,7 @@ class BuildPlateDecorator(SceneNodeDecorator):
for child in self._node.getChildren():
child.callDecoration("setBuildPlateNumber", nr)
- def getBuildPlateNumber(self):
+ def getBuildPlateNumber(self) -> int:
return self._build_plate_number
def __deepcopy__(self, memo):
diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py
index da71f6920e..2a160f6069 100644
--- a/cura/Scene/ConvexHullDecorator.py
+++ b/cura/Scene/ConvexHullDecorator.py
@@ -60,13 +60,15 @@ class ConvexHullDecorator(SceneNodeDecorator):
previous_node = self._node
# Disconnect from previous node signals
if previous_node is not None and node is not previous_node:
- previous_node.transformationChanged.disconnect(self._onChanged)
- previous_node.parentChanged.disconnect(self._onChanged)
+ previous_node.boundingBoxChanged.disconnect(self._onChanged)
super().setNode(node)
- # Mypy doesn't understand that self._node is no longer optional, so just use the node.
- node.transformationChanged.connect(self._onChanged)
- node.parentChanged.connect(self._onChanged)
+
+ node.boundingBoxChanged.connect(self._onChanged)
+
+ per_object_stack = node.callDecoration("getStack")
+ if per_object_stack:
+ per_object_stack.propertyChanged.connect(self._onSettingValueChanged)
self._onChanged()
@@ -74,26 +76,46 @@ class ConvexHullDecorator(SceneNodeDecorator):
def __deepcopy__(self, memo):
return ConvexHullDecorator()
- ## Get the unmodified 2D projected convex hull of the node (if any)
- def getConvexHull(self) -> Optional[Polygon]:
+ ## The polygon representing the 2D adhesion area.
+ # If no adhesion is used, the regular convex hull is returned
+ def getAdhesionArea(self) -> Optional[Polygon]:
if self._node is None:
return None
hull = self._compute2DConvexHull()
+ if hull is None:
+ return None
- if self._global_stack and self._node is not None and hull is not None:
- # Parent can be None if node is just loaded.
- if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node):
- hull = hull.getMinkowskiHull(Polygon(numpy.array(self._global_stack.getProperty("machine_head_polygon", "value"), numpy.float32)))
- hull = self._add2DAdhesionMargin(hull)
- return hull
+ return self._add2DAdhesionMargin(hull)
- ## Get the convex hull of the node with the full head size
+ ## Get the unmodified 2D projected convex hull of the node (if any)
+ # In case of one-at-a-time, this includes adhesion and head+fans clearance
+ def getConvexHull(self) -> Optional[Polygon]:
+ if self._node is None:
+ return None
+ if self._node.callDecoration("isNonPrintingMesh"):
+ return None
+
+ # Parent can be None if node is just loaded.
+ if self._isSingularOneAtATimeNode():
+ hull = self.getConvexHullHeadFull()
+ if hull is None:
+ return None
+ hull = self._add2DAdhesionMargin(hull)
+ return hull
+
+ return self._compute2DConvexHull()
+
+ ## For one at the time this is the convex hull of the node with the full head size
+ # In case of printing all at once this is None.
def getConvexHullHeadFull(self) -> Optional[Polygon]:
if self._node is None:
return None
- return self._compute2DConvexHeadFull()
+ if self._isSingularOneAtATimeNode():
+ return self._compute2DConvexHeadFull()
+
+ return None
@staticmethod
def hasGroupAsParent(node: "SceneNode") -> bool:
@@ -103,34 +125,47 @@ class ConvexHullDecorator(SceneNodeDecorator):
return bool(parent.callDecoration("isGroup"))
## Get convex hull of the object + head size
- # In case of printing all at once this is the same as the convex hull.
+ # In case of printing all at once this is None.
# For one at the time this is area with intersection of mirrored head
def getConvexHullHead(self) -> Optional[Polygon]:
if self._node is None:
return None
-
- if self._global_stack:
- if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node):
- head_with_fans = self._compute2DConvexHeadMin()
- if head_with_fans is None:
- return None
- head_with_fans_with_adhesion_margin = self._add2DAdhesionMargin(head_with_fans)
- return head_with_fans_with_adhesion_margin
+ if self._node.callDecoration("isNonPrintingMesh"):
+ return None
+ if self._isSingularOneAtATimeNode():
+ head_with_fans = self._compute2DConvexHeadMin()
+ if head_with_fans is None:
+ return None
+ head_with_fans_with_adhesion_margin = self._add2DAdhesionMargin(head_with_fans)
+ return head_with_fans_with_adhesion_margin
return None
## Get convex hull of the node
- # In case of printing all at once this is the same as the convex hull.
+ # In case of printing all at once this None??
# For one at the time this is the area without the head.
def getConvexHullBoundary(self) -> Optional[Polygon]:
if self._node is None:
return None
- if self._global_stack:
- if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node):
- # Printing one at a time and it's not an object in a group
- return self._compute2DConvexHull()
+ if self._node.callDecoration("isNonPrintingMesh"):
+ return None
+
+ if self._isSingularOneAtATimeNode():
+ # Printing one at a time and it's not an object in a group
+ return self._compute2DConvexHull()
return None
+ ## Get the buildplate polygon where will be printed
+ # In case of printing all at once this is the same as convex hull (no individual adhesion)
+ # For one at the time this includes the adhesion area
+ def getPrintingArea(self) -> Optional[Polygon]:
+ if self._isSingularOneAtATimeNode():
+ # In one-at-a-time mode, every printed object gets it's own adhesion
+ printing_area = self.getAdhesionArea()
+ else:
+ printing_area = self.getConvexHull()
+ return printing_area
+
## The same as recomputeConvexHull, but using a timer if it was set.
def recomputeConvexHullDelayed(self) -> None:
if self._recompute_convex_hull_timer is not None:
@@ -153,10 +188,9 @@ class ConvexHullDecorator(SceneNodeDecorator):
self._convex_hull_node = None
return
- convex_hull = self.getConvexHull()
if self._convex_hull_node:
self._convex_hull_node.setParent(None)
- hull_node = ConvexHullNode.ConvexHullNode(self._node, convex_hull, self._raft_thickness, root)
+ hull_node = ConvexHullNode.ConvexHullNode(self._node, self.getPrintingArea(), self._raft_thickness, root)
self._convex_hull_node = hull_node
def _onSettingValueChanged(self, key: str, property_name: str) -> None:
@@ -259,9 +293,13 @@ class ConvexHullDecorator(SceneNodeDecorator):
return offset_hull
def _getHeadAndFans(self) -> Polygon:
- if self._global_stack:
- return Polygon(numpy.array(self._global_stack.getHeadAndFansCoordinates(), numpy.float32))
- return Polygon()
+ if not self._global_stack:
+ return Polygon()
+
+ polygon = Polygon(numpy.array(self._global_stack.getHeadAndFansCoordinates(), numpy.float32))
+ offset_x = self._getSettingProperty("machine_nozzle_offset_x", "value")
+ offset_y = self._getSettingProperty("machine_nozzle_offset_y", "value")
+ return polygon.translate(-offset_x, -offset_y)
def _compute2DConvexHeadFull(self) -> Optional[Polygon]:
convex_hull = self._compute2DConvexHull()
@@ -393,6 +431,14 @@ class ConvexHullDecorator(SceneNodeDecorator):
return True
return self.__isDescendant(root, node.getParent())
+ ## True if print_sequence is one_at_a_time and _node is not part of a group
+ def _isSingularOneAtATimeNode(self) -> bool:
+ if self._node is None:
+ return False
+ return self._global_stack is not None \
+ and self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" \
+ and not self.hasGroupAsParent(self._node)
+
_affected_settings = [
"adhesion_type", "raft_margin", "print_sequence",
"skirt_gap", "skirt_line_count", "skirt_brim_line_width", "skirt_distance", "brim_line_count"]
@@ -400,4 +446,4 @@ class ConvexHullDecorator(SceneNodeDecorator):
## Settings that change the convex hull.
#
# If these settings change, the convex hull should be recalculated.
- _influencing_settings = {"xy_offset", "xy_offset_layer_0", "mold_enabled", "mold_width"}
+ _influencing_settings = {"xy_offset", "xy_offset_layer_0", "mold_enabled", "mold_width", "anti_overhang_mesh", "infill_mesh", "cutting_mesh"}
diff --git a/cura/Scene/ConvexHullNode.py b/cura/Scene/ConvexHullNode.py
index 90bf536308..da2713a522 100644
--- a/cura/Scene/ConvexHullNode.py
+++ b/cura/Scene/ConvexHullNode.py
@@ -1,6 +1,6 @@
# Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional
+from typing import Optional, TYPE_CHECKING
from UM.Application import Application
from UM.Math.Polygon import Polygon
@@ -11,6 +11,9 @@ from UM.Math.Color import Color
from UM.Mesh.MeshBuilder import MeshBuilder # To create a mesh to display the convex hull with.
from UM.View.GL.OpenGL import OpenGL
+if TYPE_CHECKING:
+ from UM.Mesh.MeshData import MeshData
+
class ConvexHullNode(SceneNode):
shader = None # To prevent the shader from being re-built over and over again, only load it once.
@@ -43,7 +46,8 @@ class ConvexHullNode(SceneNode):
# The node this mesh is "watching"
self._node = node
- self._convex_hull_head_mesh = None
+ # Area of the head + fans for display as a shadow on the buildplate
+ self._convex_hull_head_mesh = None # type: Optional[MeshData]
self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged)
self._onNodeDecoratorsChanged(self._node)
@@ -76,14 +80,17 @@ class ConvexHullNode(SceneNode):
if self.getParent():
if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate:
+ # The object itself (+ adhesion in one-at-a-time mode)
renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
if self._convex_hull_head_mesh:
+ # The full head. Rendered as a hint to the user: If this area overlaps another object A; this object
+ # cannot be printed after A, because the head would hit A while printing the current object
renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
return True
def _onNodeDecoratorsChanged(self, node: SceneNode) -> None:
- convex_hull_head = self._node.callDecoration("getConvexHullHead")
+ convex_hull_head = self._node.callDecoration("getConvexHullHeadFull")
if convex_hull_head:
convex_hull_head_builder = MeshBuilder()
convex_hull_head_builder.addConvexPolygon(convex_hull_head.getPoints(), self._mesh_height - self._thickness)
diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py
index 9f26ea7cc3..91ff26cadc 100644
--- a/cura/Scene/CuraSceneController.py
+++ b/cura/Scene/CuraSceneController.py
@@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt, pyqtSlot, QObject
from PyQt5.QtWidgets import QApplication
from UM.Scene.Camera import Camera
-from cura.ObjectsModel import ObjectsModel
+from cura.UI.ObjectsModel import ObjectsModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from UM.Application import Application
diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py
index 259c273329..eb609def5a 100644
--- a/cura/Scene/CuraSceneNode.py
+++ b/cura/Scene/CuraSceneNode.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from copy import deepcopy
@@ -6,13 +6,14 @@ from typing import cast, Dict, List, Optional
from UM.Application import Application
from UM.Math.AxisAlignedBox import AxisAlignedBox
-from UM.Math.Polygon import Polygon #For typing.
+from UM.Math.Polygon import Polygon # For typing.
from UM.Scene.SceneNode import SceneNode
-from UM.Scene.SceneNodeDecorator import SceneNodeDecorator #To cast the deepcopy of every decorator back to SceneNodeDecorator.
+from UM.Scene.SceneNodeDecorator import SceneNodeDecorator # To cast the deepcopy of every decorator back to SceneNodeDecorator.
+
+import cura.CuraApplication # To get the build plate.
+from cura.Settings.ExtruderStack import ExtruderStack # For typing.
+from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator # For per-object settings.
-import cura.CuraApplication #To get the build plate.
-from cura.Settings.ExtruderStack import ExtruderStack #For typing.
-from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator #For per-object settings.
## Scene nodes that are models are only seen when selecting the corresponding build plate
# Note that many other nodes can just be UM SceneNode objects.
@@ -20,7 +21,7 @@ class CuraSceneNode(SceneNode):
def __init__(self, parent: Optional["SceneNode"] = None, visible: bool = True, name: str = "", no_setting_override: bool = False) -> None:
super().__init__(parent = parent, visible = visible, name = name)
if not no_setting_override:
- self.addDecorator(SettingOverrideDecorator()) # now we always have a getActiveExtruderPosition, unless explicitly disabled
+ self.addDecorator(SettingOverrideDecorator()) # Now we always have a getActiveExtruderPosition, unless explicitly disabled
self._outside_buildarea = False
def setOutsideBuildArea(self, new_value: bool) -> None:
@@ -58,7 +59,7 @@ class CuraSceneNode(SceneNode):
if extruder_id is not None:
if extruder_id == extruder.getId():
return extruder
- else: # If the id is unknown, then return the extruder in the position 0
+ else: # If the id is unknown, then return the extruder in the position 0
try:
if extruder.getMetaDataEntry("position", default = "0") == "0": # Check if the position is zero
return extruder
@@ -85,24 +86,14 @@ class CuraSceneNode(SceneNode):
1.0
]
- ## Return if the provided bbox collides with the bbox of this scene node
- def collidesWithBbox(self, check_bbox: AxisAlignedBox) -> bool:
- bbox = self.getBoundingBox()
- if bbox is not None:
- # Mark the node as outside the build volume if the bounding box test fails.
- if check_bbox.intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection:
- return True
-
- return False
-
## Return if any area collides with the convex hull of this scene node
- def collidesWithArea(self, areas: List[Polygon]) -> bool:
- convex_hull = self.callDecoration("getConvexHull")
+ def collidesWithAreas(self, areas: List[Polygon]) -> bool:
+ convex_hull = self.callDecoration("getPrintingArea")
if convex_hull:
if not convex_hull.isValid():
return False
- # Check for collisions between disallowed areas and the object
+ # Check for collisions between provided areas and the object
for area in areas:
overlap = convex_hull.intersectsPolygon(area)
if overlap is None:
@@ -112,21 +103,24 @@ class CuraSceneNode(SceneNode):
## Override of SceneNode._calculateAABB to exclude non-printing-meshes from bounding box
def _calculateAABB(self) -> None:
+ self._aabb = None
if self._mesh_data:
- aabb = self._mesh_data.getExtents(self.getWorldTransformation())
+ self._aabb = self._mesh_data.getExtents(self.getWorldTransformation())
else: # If there is no mesh_data, use a boundingbox that encompasses the local (0,0,0)
position = self.getWorldPosition()
- aabb = AxisAlignedBox(minimum = position, maximum = position)
+ self._aabb = AxisAlignedBox(minimum=position, maximum=position)
- for child in self._children:
+ for child in self.getAllChildren():
if child.callDecoration("isNonPrintingMesh"):
# Non-printing-meshes inside a group should not affect push apart or drop to build plate
continue
- if aabb is None:
- aabb = child.getBoundingBox()
+ if not child.getMeshData():
+ # Nodes without mesh data should not affect bounding boxes of their parents.
+ continue
+ if self._aabb is None:
+ self._aabb = child.getBoundingBox()
else:
- aabb = aabb + child.getBoundingBox()
- self._aabb = aabb
+ self._aabb = self._aabb + child.getBoundingBox()
## Taken from SceneNode, but replaced SceneNode with CuraSceneNode
def __deepcopy__(self, memo: Dict[int, object]) -> "CuraSceneNode":
diff --git a/cura/Scene/GCodeListDecorator.py b/cura/Scene/GCodeListDecorator.py
index d3dadb3f23..6c52fb89bf 100644
--- a/cura/Scene/GCodeListDecorator.py
+++ b/cura/Scene/GCodeListDecorator.py
@@ -1,11 +1,18 @@
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
-from typing import List
+from typing import List, Optional
class GCodeListDecorator(SceneNodeDecorator):
def __init__(self) -> None:
super().__init__()
self._gcode_list = [] # type: List[str]
+ self._filename = None # type: Optional[str]
+
+ def getGcodeFileName(self) -> Optional[str]:
+ return self._filename
+
+ def setGcodeFileName(self, filename: str) -> None:
+ self._filename = filename
def getGCodeList(self) -> List[str]:
return self._gcode_list
diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py
index 133e04e8fc..92f06929d2 100644
--- a/cura/Settings/ContainerManager.py
+++ b/cura/Settings/ContainerManager.py
@@ -1,15 +1,14 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os
import urllib.parse
import uuid
-from typing import Dict, Union, Any, TYPE_CHECKING, List
+from typing import Any, cast, Dict, List, TYPE_CHECKING, Union
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtWidgets import QMessageBox
-
from UM.i18n import i18nCatalog
from UM.FlameProfiler import pyqtSlot
from UM.Logger import Logger
@@ -17,21 +16,19 @@ from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
from UM.Platform import Platform
from UM.SaveFile import SaveFile
from UM.Settings.ContainerFormatError import ContainerFormatError
+from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.InstanceContainer import InstanceContainer
+import cura.CuraApplication
+from cura.Machines.ContainerTree import ContainerTree
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.MaterialNode import MaterialNode
from cura.Machines.QualityChangesGroup import QualityChangesGroup
- from UM.PluginRegistry import PluginRegistry
- from cura.Settings.MachineManager import MachineManager
- from cura.Machines.MaterialManager import MaterialManager
- from cura.Machines.QualityManager import QualityManager
- from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
catalog = i18nCatalog("cura")
@@ -47,20 +44,16 @@ class ContainerManager(QObject):
if ContainerManager.__instance is not None:
raise RuntimeError("Try to create singleton '%s' more than once" % self.__class__.__name__)
ContainerManager.__instance = self
+ try:
+ super().__init__(parent = application)
+ except TypeError:
+ super().__init__()
- super().__init__(parent = application)
-
- self._application = application # type: CuraApplication
- self._plugin_registry = self._application.getPluginRegistry() # type: PluginRegistry
- self._container_registry = self._application.getContainerRegistry() # type: CuraContainerRegistry
- self._machine_manager = self._application.getMachineManager() # type: MachineManager
- self._material_manager = self._application.getMaterialManager() # type: MaterialManager
- self._quality_manager = self._application.getQualityManager() # type: QualityManager
self._container_name_filters = {} # type: Dict[str, Dict[str, Any]]
@pyqtSlot(str, str, result=str)
def getContainerMetaDataEntry(self, container_id: str, entry_names: str) -> str:
- metadatas = self._container_registry.findContainersMetadata(id = container_id)
+ metadatas = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().findContainersMetadata(id = container_id)
if not metadatas:
Logger.log("w", "Could not get metadata of container %s because it was not found.", container_id)
return ""
@@ -89,15 +82,19 @@ class ContainerManager(QObject):
# Update: In order for QML to use objects and sub objects, those (sub) objects must all be QObject. Is that what we want?
@pyqtSlot("QVariant", str, str)
def setContainerMetaDataEntry(self, container_node: "ContainerNode", entry_name: str, entry_value: str) -> bool:
+ if container_node.container is None:
+ Logger.log("w", "Container node {0} doesn't have a container.".format(container_node.container_id))
+ return False
root_material_id = container_node.getMetaDataEntry("base_file", "")
- if self._container_registry.isReadOnly(root_material_id):
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ if container_registry.isReadOnly(root_material_id):
Logger.log("w", "Cannot set metadata of read-only container %s.", root_material_id)
return False
-
- material_group = self._material_manager.getMaterialGroup(root_material_id)
- if material_group is None:
- Logger.log("w", "Unable to find material group for: %s.", root_material_id)
+ root_material_query = container_registry.findContainers(id = root_material_id)
+ if not root_material_query:
+ Logger.log("w", "Unable to find root material: {root_material}.".format(root_material = root_material_id))
return False
+ root_material = root_material_query[0]
entries = entry_name.split("/")
entry_name = entries.pop()
@@ -105,7 +102,7 @@ class ContainerManager(QObject):
sub_item_changed = False
if entries:
root_name = entries.pop(0)
- root = material_group.root_material_node.getMetaDataEntry(root_name)
+ root = root_material.getMetaDataEntry(root_name)
item = root
for _ in range(len(entries)):
@@ -118,16 +115,14 @@ class ContainerManager(QObject):
entry_name = root_name
entry_value = root
- container = material_group.root_material_node.getContainer()
- if container is not None:
- container.setMetaDataEntry(entry_name, entry_value)
- if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed.
- container.metaDataChanged.emit(container)
+ root_material.setMetaDataEntry(entry_name, entry_value)
+ if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed.
+ root_material.metaDataChanged.emit(root_material)
return True
@pyqtSlot(str, result = str)
def makeUniqueName(self, original_name: str) -> str:
- return self._container_registry.uniqueName(original_name)
+ return cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().uniqueName(original_name)
## Get a list of string that can be used as name filters for a Qt File Dialog
#
@@ -182,7 +177,7 @@ class ContainerManager(QObject):
else:
mime_type = self._container_name_filters[file_type]["mime"]
- containers = self._container_registry.findContainers(id = container_id)
+ containers = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().findContainers(id = container_id)
if not containers:
return {"status": "error", "message": "Container not found"}
container = containers[0]
@@ -240,18 +235,19 @@ class ContainerManager(QObject):
except MimeTypeNotFoundError:
return {"status": "error", "message": "Could not determine mime type of file"}
- container_type = self._container_registry.getContainerForMimeType(mime_type)
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ container_type = container_registry.getContainerForMimeType(mime_type)
if not container_type:
return {"status": "error", "message": "Could not find a container to handle the specified file."}
container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url)))
- container_id = self._container_registry.uniqueName(container_id)
+ container_id = container_registry.uniqueName(container_id)
container = container_type(container_id)
try:
with open(file_url, "rt", encoding = "utf-8") as f:
- container.deserialize(f.read())
+ container.deserialize(f.read(), file_url)
except PermissionError:
return {"status": "error", "message": "Permission denied when trying to read the file."}
except ContainerFormatError:
@@ -261,7 +257,7 @@ class ContainerManager(QObject):
container.setDirty(True)
- self._container_registry.addContainer(container)
+ container_registry.addContainer(container)
return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())}
@@ -273,44 +269,55 @@ class ContainerManager(QObject):
# \return \type{bool} True if successful, False if not.
@pyqtSlot(result = bool)
def updateQualityChanges(self) -> bool:
- global_stack = self._machine_manager.activeMachine
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ global_stack = application.getMachineManager().activeMachine
if not global_stack:
return False
- self._machine_manager.blurSettings.emit()
+ application.getMachineManager().blurSettings.emit()
current_quality_changes_name = global_stack.qualityChanges.getName()
current_quality_type = global_stack.quality.getMetaDataEntry("quality_type")
extruder_stacks = list(global_stack.extruders.values())
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ machine_definition_id = ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
for stack in [global_stack] + extruder_stacks:
# Find the quality_changes container for this stack and merge the contents of the top container into it.
quality_changes = stack.qualityChanges
if quality_changes.getId() == "empty_quality_changes":
- quality_changes = self._quality_manager._createQualityChanges(current_quality_type, current_quality_changes_name,
- global_stack, stack)
- self._container_registry.addContainer(quality_changes)
+ quality_changes = InstanceContainer(container_registry.uniqueName((stack.getId() + "_" + current_quality_changes_name).lower().replace(" ", "_")))
+ quality_changes.setName(current_quality_changes_name)
+ quality_changes.setMetaDataEntry("type", "quality_changes")
+ quality_changes.setMetaDataEntry("quality_type", current_quality_type)
+ if stack.getMetaDataEntry("position") is not None: # Extruder stacks.
+ quality_changes.setMetaDataEntry("position", stack.getMetaDataEntry("position"))
+ quality_changes.setMetaDataEntry("intent_category", stack.quality.getMetaDataEntry("intent_category", "default"))
+ quality_changes.setMetaDataEntry("setting_version", application.SettingVersion)
+ quality_changes.setDefinition(machine_definition_id)
+ container_registry.addContainer(quality_changes)
stack.qualityChanges = quality_changes
- if not quality_changes or self._container_registry.isReadOnly(quality_changes.getId()):
+ if not quality_changes or container_registry.isReadOnly(quality_changes.getId()):
Logger.log("e", "Could not update quality of a nonexistant or read only quality profile in stack %s", stack.getId())
continue
self._performMerge(quality_changes, stack.getTop())
- self._machine_manager.activeQualityChangesGroupChanged.emit()
+ cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeQualityChangesGroupChanged.emit()
return True
## Clear the top-most (user) containers of the active stacks.
@pyqtSlot()
def clearUserContainers(self) -> None:
- self._machine_manager.blurSettings.emit()
+ machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
+ machine_manager.blurSettings.emit()
send_emits_containers = []
# Go through global and extruder stacks and clear their topmost container (the user settings).
- global_stack = self._machine_manager.activeMachine
+ global_stack = machine_manager.activeMachine
extruder_stacks = list(global_stack.extruders.values())
for stack in [global_stack] + extruder_stacks:
container = stack.userChanges
@@ -318,40 +325,38 @@ class ContainerManager(QObject):
send_emits_containers.append(container)
# user changes are possibly added to make the current setup match the current enabled extruders
- self._machine_manager.correctExtruderSettings()
+ machine_manager.correctExtruderSettings()
for container in send_emits_containers:
container.sendPostponedEmits()
## Get a list of materials that have the same GUID as the reference material
#
- # \param material_id \type{str} the id of the material for which to get the linked materials.
- # \return \type{list} a list of names of materials with the same GUID
+ # \param material_node The node representing the material for which to get
+ # the same GUID.
+ # \param exclude_self Whether to include the name of the material you
+ # provided.
+ # \return A list of names of materials with the same GUID.
@pyqtSlot("QVariant", bool, result = "QStringList")
- def getLinkedMaterials(self, material_node: "MaterialNode", exclude_self: bool = False):
- guid = material_node.getMetaDataEntry("GUID", "")
-
- self_root_material_id = material_node.getMetaDataEntry("base_file")
- material_group_list = self._material_manager.getMaterialGroupListByGUID(guid)
-
- linked_material_names = []
- if material_group_list:
- for material_group in material_group_list:
- if exclude_self and material_group.name == self_root_material_id:
- continue
- linked_material_names.append(material_group.root_material_node.getMetaDataEntry("name", ""))
- return linked_material_names
+ def getLinkedMaterials(self, material_node: "MaterialNode", exclude_self: bool = False) -> List[str]:
+ same_guid = ContainerRegistry.getInstance().findInstanceContainersMetadata(GUID = material_node.guid)
+ if exclude_self:
+ return list({meta["name"] for meta in same_guid if meta["base_file"] != material_node.base_file})
+ else:
+ return list({meta["name"] for meta in same_guid})
## Unlink a material from all other materials by creating a new GUID
# \param material_id \type{str} the id of the material to create a new GUID for.
@pyqtSlot("QVariant")
def unlinkMaterial(self, material_node: "MaterialNode") -> None:
# Get the material group
- material_group = self._material_manager.getMaterialGroup(material_node.getMetaDataEntry("base_file", ""))
-
- if material_group is None:
+ if material_node.container is None: # Failed to lazy-load this container.
+ return
+ root_material_query = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().findInstanceContainers(id = material_node.getMetaDataEntry("base_file", ""))
+ if not root_material_query:
Logger.log("w", "Unable to find material group for %s", material_node)
return
+ root_material = root_material_query[0]
# Generate a new GUID
new_guid = str(uuid.uuid4())
@@ -359,9 +364,7 @@ class ContainerManager(QObject):
# Update the GUID
# NOTE: We only need to set the root material container because XmlMaterialProfile.setMetaDataEntry() will
# take care of the derived containers too
- container = material_group.root_material_node.getContainer()
- if container is not None:
- container.setMetaDataEntry("GUID", new_guid)
+ root_material.setMetaDataEntry("GUID", new_guid)
def _performMerge(self, merge_into: InstanceContainer, merge: InstanceContainer, clear_settings: bool = True) -> None:
if merge == merge_into:
@@ -375,14 +378,16 @@ class ContainerManager(QObject):
def _updateContainerNameFilters(self) -> None:
self._container_name_filters = {}
- for plugin_id, container_type in self._container_registry.getContainerTypes():
+ plugin_registry = cura.CuraApplication.CuraApplication.getInstance().getPluginRegistry()
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ for plugin_id, container_type in container_registry.getContainerTypes():
# Ignore default container types since those are not plugins
if container_type in (InstanceContainer, ContainerStack, DefinitionContainer):
continue
serialize_type = ""
try:
- plugin_metadata = self._plugin_registry.getMetaData(plugin_id)
+ plugin_metadata = plugin_registry.getMetaData(plugin_id)
if plugin_metadata:
serialize_type = plugin_metadata["settings_container"]["type"]
else:
@@ -390,7 +395,7 @@ class ContainerManager(QObject):
except KeyError as e:
continue
- mime_type = self._container_registry.getMimeTypeForContainer(container_type)
+ mime_type = container_registry.getMimeTypeForContainer(container_type)
if mime_type is None:
continue
entry = {
@@ -426,7 +431,7 @@ class ContainerManager(QObject):
path = file_url.toLocalFile()
if not path:
return {"status": "error", "message": catalog.i18nc("@info:status", "Invalid file URL:") + " " + str(file_url)}
- return self._container_registry.importProfile(path)
+ return cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().importProfile(path)
@pyqtSlot(QObject, QUrl, str)
def exportQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", file_url: QUrl, file_type: str) -> None:
@@ -436,8 +441,11 @@ class ContainerManager(QObject):
if not path:
return
- container_list = [n.getContainer() for n in quality_changes_group.getAllNodes() if n.getContainer() is not None]
- self._container_registry.exportQualityProfile(container_list, path, file_type)
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
+ container_list = [cast(InstanceContainer, container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])[0])] # type: List[InstanceContainer]
+ for metadata in quality_changes_group.metadata_per_extruder.values():
+ container_list.append(cast(InstanceContainer, container_registry.findContainers(id = metadata["id"])[0]))
+ cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().exportQualityProfile(container_list, path, file_type)
__instance = None # type: ContainerManager
diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py
index a9f79d63d3..f6028e9d4d 100644
--- a/cura/Settings/CuraContainerRegistry.py
+++ b/cura/Settings/CuraContainerRegistry.py
@@ -1,11 +1,11 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os
import re
import configparser
-from typing import cast, Dict, Optional
+from typing import Any, cast, Dict, Optional, List, Union
from PyQt5.QtWidgets import QMessageBox
from UM.Decorators import override
@@ -20,14 +20,16 @@ from UM.Logger import Logger
from UM.Message import Message
from UM.Platform import Platform
from UM.PluginRegistry import PluginRegistry # For getting the possible profile writers to write with.
-from UM.Util import parseBool
from UM.Resources import Resources
+from UM.Util import parseBool
+from cura.ReaderWriters.ProfileWriter import ProfileWriter
from . import ExtruderStack
from . import GlobalStack
import cura.CuraApplication
-from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
+from cura.Settings.cura_empty_instance_containers import empty_quality_container
+from cura.Machines.ContainerTree import ContainerTree
from cura.ReaderWriters.ProfileReader import NoProfileException, ProfileReader
from UM.i18n import i18nCatalog
@@ -50,10 +52,10 @@ class CuraContainerRegistry(ContainerRegistry):
# This will also try to convert a ContainerStack to either Extruder or
# Global stack based on metadata information.
@override(ContainerRegistry)
- def addContainer(self, container):
+ def addContainer(self, container: ContainerInterface) -> None:
# Note: Intentional check with type() because we want to ignore subclasses
if type(container) == ContainerStack:
- container = self._convertContainerStack(container)
+ container = self._convertContainerStack(cast(ContainerStack, container))
if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()):
# Check against setting version of the definition.
@@ -61,7 +63,7 @@ class CuraContainerRegistry(ContainerRegistry):
actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0))
if required_setting_version != actual_setting_version:
Logger.log("w", "Instance container {container_id} is outdated. Its setting version is {actual_setting_version} but it should be {required_setting_version}.".format(container_id = container.getId(), actual_setting_version = actual_setting_version, required_setting_version = required_setting_version))
- return #Don't add.
+ return # Don't add.
super().addContainer(container)
@@ -71,9 +73,9 @@ class CuraContainerRegistry(ContainerRegistry):
# \param new_name \type{string} Base name, which may not be unique
# \param fallback_name \type{string} Name to use when (stripped) new_name is empty
# \return \type{string} Name that is unique for the specified type and name/id
- def createUniqueName(self, container_type, current_name, new_name, fallback_name):
+ def createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str:
new_name = new_name.strip()
- num_check = re.compile("(.*?)\s*#\d+$").match(new_name)
+ num_check = re.compile(r"(.*?)\s*#\d+$").match(new_name)
if num_check:
new_name = num_check.group(1)
if new_name == "":
@@ -92,7 +94,7 @@ class CuraContainerRegistry(ContainerRegistry):
# Both the id and the name are checked, because they may not be the same and it is better if they are both unique
# \param container_type \type{string} Type of the container (machine, quality, ...)
# \param container_name \type{string} Name to check
- def _containerExists(self, container_type, container_name):
+ def _containerExists(self, container_type: str, container_name: str):
container_class = ContainerStack if container_type == "machine" else InstanceContainer
return self.findContainersMetadata(container_type = container_class, id = container_name, type = container_type, ignore_case = True) or \
@@ -100,16 +102,18 @@ class CuraContainerRegistry(ContainerRegistry):
## Exports an profile to a file
#
- # \param instance_ids \type{list} the IDs of the profiles to export.
+ # \param container_list \type{list} the containers to export. This is not
+ # necessarily in any order!
# \param file_name \type{str} the full path and filename to export to.
# \param file_type \type{str} the file type with the format " (*.)"
- def exportQualityProfile(self, container_list, file_name, file_type):
+ # \return True if the export succeeded, false otherwise.
+ def exportQualityProfile(self, container_list: List[InstanceContainer], file_name: str, file_type: str) -> bool:
# Parse the fileType to deduce what plugin can save the file format.
# fileType has the format " (*.)"
split = file_type.rfind(" (*.") # Find where the description ends and the extension starts.
if split < 0: # Not found. Invalid format.
Logger.log("e", "Invalid file format identifier %s", file_type)
- return
+ return False
description = file_type[:split]
extension = file_type[split + 4:-1] # Leave out the " (*." and ")".
if not file_name.endswith("." + extension): # Auto-fill the extension if the user did not provide any.
@@ -121,10 +125,12 @@ class CuraContainerRegistry(ContainerRegistry):
result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"),
catalog.i18nc("@label Don't translate the XML tag !", "The file {0} already exists. Are you sure you want to overwrite it?").format(file_name))
if result == QMessageBox.No:
- return
+ return False
profile_writer = self._findProfileWriter(extension, description)
try:
+ if profile_writer is None:
+ raise Exception("Unable to find a profile writer")
success = profile_writer.write(file_name, container_list)
except Exception as e:
Logger.log("e", "Failed to export profile to %s: %s", file_name, str(e))
@@ -132,23 +138,24 @@ class CuraContainerRegistry(ContainerRegistry):
lifetime = 0,
title = catalog.i18nc("@info:title", "Error"))
m.show()
- return
+ return False
if not success:
Logger.log("w", "Failed to export profile to %s: Writer plugin reported failure.", file_name)
m = Message(catalog.i18nc("@info:status Don't translate the XML tag !", "Failed to export profile to {0}: Writer plugin reported failure.", file_name),
lifetime = 0,
title = catalog.i18nc("@info:title", "Error"))
m.show()
- return
+ return False
m = Message(catalog.i18nc("@info:status Don't translate the XML tag !", "Exported profile to {0}", file_name),
title = catalog.i18nc("@info:title", "Export succeeded"))
m.show()
+ return True
## Gets the plugin object matching the criteria
# \param extension
# \param description
# \return The plugin object matching the given extension and description.
- def _findProfileWriter(self, extension, description):
+ def _findProfileWriter(self, extension: str, description: str) -> Optional[ProfileWriter]:
plugin_registry = PluginRegistry.getInstance()
for plugin_id, meta_data in self._getIOPlugins("profile_writer"):
for supported_type in meta_data["profile_writer"]: # All file types this plugin can supposedly write.
@@ -156,7 +163,7 @@ class CuraContainerRegistry(ContainerRegistry):
if supported_extension == extension: # This plugin supports a file type with the same extension.
supported_description = supported_type.get("description", None)
if supported_description == description: # The description is also identical. Assume it's the same file type.
- return plugin_registry.getPluginObject(plugin_id)
+ return cast(ProfileWriter, plugin_registry.getPluginObject(plugin_id))
return None
## Imports a profile from a file
@@ -169,17 +176,18 @@ class CuraContainerRegistry(ContainerRegistry):
if not file_name:
return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags !", "Failed to import profile from {0}: {1}", file_name, "Invalid path")}
- plugin_registry = PluginRegistry.getInstance()
- extension = file_name.split(".")[-1]
-
global_stack = Application.getInstance().getGlobalContainerStack()
if not global_stack:
return {"status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags !", "Can't import profile from {0} before a printer is added.", file_name)}
+ container_tree = ContainerTree.getInstance()
machine_extruders = []
for position in sorted(global_stack.extruders):
machine_extruders.append(global_stack.extruders[position])
+ plugin_registry = PluginRegistry.getInstance()
+ extension = file_name.split(".")[-1]
+
for plugin_id, meta_data in self._getIOPlugins("profile_reader"):
if meta_data["profile_reader"][0]["extension"] != extension:
continue
@@ -221,7 +229,7 @@ class CuraContainerRegistry(ContainerRegistry):
# Make sure we have a profile_definition in the file:
if profile_definition is None:
break
- machine_definitions = self.findDefinitionContainers(id = profile_definition)
+ machine_definitions = self.findContainers(id = profile_definition)
if not machine_definitions:
Logger.log("e", "Incorrect profile [%s]. Unknown machine type [%s]", file_name, profile_definition)
return {"status": "error",
@@ -231,17 +239,17 @@ class CuraContainerRegistry(ContainerRegistry):
# Get the expected machine definition.
# i.e.: We expect gcode for a UM2 Extended to be defined as normal UM2 gcode...
- profile_definition = getMachineDefinitionIDForQualitySearch(machine_definition)
- expected_machine_definition = getMachineDefinitionIDForQualitySearch(global_stack.definition)
+ has_machine_quality = parseBool(machine_definition.getMetaDataEntry("has_machine_quality", "false"))
+ profile_definition = machine_definition.getMetaDataEntry("quality_definition", machine_definition.getId()) if has_machine_quality else "fdmprinter"
+ expected_machine_definition = container_tree.machines[global_stack.definition.getId()].quality_definition
# And check if the profile_definition matches either one (showing error if not):
if profile_definition != expected_machine_definition:
- Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition)
- return { "status": "error",
- "message": catalog.i18nc("@info:status Don't translate the XML tags !", "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)}
+ Logger.log("d", "Profile {file_name} is for machine {profile_definition}, but the current active machine is {expected_machine_definition}. Changing profile's definition.".format(file_name = file_name, profile_definition = profile_definition, expected_machine_definition = expected_machine_definition))
+ global_profile.setMetaDataEntry("definition", expected_machine_definition)
+ for extruder_profile in extruder_profiles:
+ extruder_profile.setMetaDataEntry("definition", expected_machine_definition)
- # Fix the global quality profile's definition field in case it's not correct
- global_profile.setMetaDataEntry("definition", expected_machine_definition)
quality_name = global_profile.getName()
quality_type = global_profile.getMetaDataEntry("quality_type")
@@ -264,7 +272,6 @@ class CuraContainerRegistry(ContainerRegistry):
profile.setMetaDataEntry("type", "quality_changes")
profile.setMetaDataEntry("definition", expected_machine_definition)
profile.setMetaDataEntry("quality_type", quality_type)
- profile.setMetaDataEntry("position", "0")
profile.setDirty(True)
if idx == 0:
# Move all per-extruder settings to the first extruder's quality_changes
@@ -281,13 +288,14 @@ class CuraContainerRegistry(ContainerRegistry):
profile.addInstance(new_instance)
profile.setDirty(True)
- global_profile.removeInstance(qc_setting_key, postpone_emit=True)
+ global_profile.removeInstance(qc_setting_key, postpone_emit = True)
extruder_profiles.append(profile)
for profile in extruder_profiles:
profile_or_list.append(profile)
# Import all profiles
+ profile_ids_added = [] # type: List[str]
for profile_index, profile in enumerate(profile_or_list):
if profile_index == 0:
# This is assumed to be the global profile
@@ -308,11 +316,15 @@ class CuraContainerRegistry(ContainerRegistry):
result = self._configureProfile(profile, profile_id, new_name, expected_machine_definition)
if result is not None:
- return {"status": "error", "message": catalog.i18nc(
- "@info:status Don't translate the XML tags or !",
- "Failed to import profile from {0}:",
- file_name) + " " + result + ""}
+ # Remove any profiles that did got added.
+ for profile_id in profile_ids_added:
+ self.removeContainer(profile_id)
+ return {"status": "error", "message": catalog.i18nc(
+ "@info:status Don't translate the XML tag !",
+ "Failed to import profile from {0}:",
+ file_name) + " " + result}
+ profile_ids_added.append(profile.getId())
return {"status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile_or_list[0].getName())}
# This message is throw when the profile reader doesn't find any profile in the file
@@ -322,11 +334,28 @@ class CuraContainerRegistry(ContainerRegistry):
return {"status": "error", "message": catalog.i18nc("@info:status", "Profile {0} has an unknown file type or is corrupted.", file_name)}
@override(ContainerRegistry)
- def load(self):
+ def load(self) -> None:
super().load()
self._registerSingleExtrusionMachinesExtruderStacks()
self._connectUpgradedExtruderStacksToMachines()
+ ## Check if the metadata for a container is okay before adding it.
+ #
+ # This overrides the one from UM.Settings.ContainerRegistry because we
+ # also require that the setting_version is correct.
+ @override(ContainerRegistry)
+ def _isMetadataValid(self, metadata: Optional[Dict[str, Any]]) -> bool:
+ if metadata is None:
+ return False
+ if "setting_version" not in metadata:
+ return False
+ try:
+ if int(metadata["setting_version"]) != cura.CuraApplication.CuraApplication.SettingVersion:
+ return False
+ except ValueError: #Not parsable as int.
+ return False
+ return True
+
## Update an imported profile to match the current machine configuration.
#
# \param profile The profile to configure.
@@ -358,21 +387,40 @@ class CuraContainerRegistry(ContainerRegistry):
global_stack = Application.getInstance().getGlobalContainerStack()
if global_stack is None:
return None
- definition_id = getMachineDefinitionIDForQualitySearch(global_stack.definition)
+ definition_id = ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
profile.setDefinition(definition_id)
# Check to make sure the imported profile actually makes sense in context of the current configuration.
# This prevents issues where importing a "draft" profile for a machine without "draft" qualities would report as
# successfully imported but then fail to show up.
- quality_manager = cura.CuraApplication.CuraApplication.getInstance()._quality_manager
- quality_group_dict = quality_manager.getQualityGroupsForMachineDefinition(global_stack)
- if quality_type not in quality_group_dict:
+ quality_group_dict = ContainerTree.getInstance().getCurrentQualityGroups()
+ # "not_supported" profiles can be imported.
+ if quality_type != empty_quality_container.getMetaDataEntry("quality_type") and quality_type not in quality_group_dict:
return catalog.i18nc("@info:status", "Could not find a quality type {0} for the current configuration.", quality_type)
ContainerRegistry.getInstance().addContainer(profile)
return None
+ @override(ContainerRegistry)
+ def saveDirtyContainers(self) -> None:
+ # Lock file for "more" atomically loading and saving to/from config dir.
+ with self.lockFile():
+ # Save base files first
+ for instance in self.findDirtyContainers(container_type=InstanceContainer):
+ if instance.getMetaDataEntry("removed"):
+ continue
+ if instance.getId() == instance.getMetaData().get("base_file"):
+ self.saveContainer(instance)
+
+ for instance in self.findDirtyContainers(container_type=InstanceContainer):
+ if instance.getMetaDataEntry("removed"):
+ continue
+ self.saveContainer(instance)
+
+ for stack in self.findContainerStacks():
+ self.saveContainer(stack)
+
## Gets a list of profile writer plugins
# \return List of tuples of (plugin_id, meta_data).
def _getIOPlugins(self, io_type):
@@ -387,7 +435,7 @@ class CuraContainerRegistry(ContainerRegistry):
return result
## Convert an "old-style" pure ContainerStack to either an Extruder or Global stack.
- def _convertContainerStack(self, container):
+ def _convertContainerStack(self, container: ContainerStack) -> Union[ExtruderStack.ExtruderStack, GlobalStack.GlobalStack]:
assert type(container) == ContainerStack
container_type = container.getMetaDataEntry("type")
@@ -411,14 +459,14 @@ class CuraContainerRegistry(ContainerRegistry):
return new_stack
- def _registerSingleExtrusionMachinesExtruderStacks(self):
+ def _registerSingleExtrusionMachinesExtruderStacks(self) -> None:
machines = self.findContainerStacks(type = "machine", machine_extruder_trains = {"0": "fdmextruder"})
for machine in machines:
extruder_stacks = self.findContainerStacks(type = "extruder_train", machine = machine.getId())
if not extruder_stacks:
self.addExtruderStackForSingleExtrusionMachine(machine, "fdmextruder")
- def _onContainerAdded(self, container):
+ def _onContainerAdded(self, container: ContainerInterface) -> None:
# We don't have all the machines loaded in the beginning, so in order to add the missing extruder stack
# for single extrusion machines, we subscribe to the containerAdded signal, and whenever a global stack
# is added, we check to see if an extruder stack needs to be added.
@@ -568,6 +616,7 @@ class CuraContainerRegistry(ContainerRegistry):
extruder_quality_changes_container.setMetaDataEntry("setting_version", application.SettingVersion)
extruder_quality_changes_container.setMetaDataEntry("position", extruder_definition.getMetaDataEntry("position"))
extruder_quality_changes_container.setMetaDataEntry("quality_type", machine_quality_changes.getMetaDataEntry("quality_type"))
+ extruder_quality_changes_container.setMetaDataEntry("intent_category", "default") # Intent categories weren't a thing back then.
extruder_quality_changes_container.setDefinition(machine_quality_changes.getDefinition().getId())
self.addContainer(extruder_quality_changes_container)
@@ -652,7 +701,7 @@ class CuraContainerRegistry(ContainerRegistry):
return extruder_stack
- def _findQualityChangesContainerInCuraFolder(self, name):
+ def _findQualityChangesContainerInCuraFolder(self, name: str) -> Optional[InstanceContainer]:
quality_changes_dir = Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.QualityChangesInstanceContainer)
instance_container = None
@@ -665,7 +714,7 @@ class CuraContainerRegistry(ContainerRegistry):
parser = configparser.ConfigParser(interpolation = None)
try:
parser.read([file_path])
- except:
+ except Exception:
# Skip, it is not a valid stack file
continue
@@ -697,7 +746,7 @@ class CuraContainerRegistry(ContainerRegistry):
# due to problems with loading order, some stacks may not have the proper next stack
# set after upgrading, because the proper global stack was not yet loaded. This method
# makes sure those extruders also get the right stack set.
- def _connectUpgradedExtruderStacksToMachines(self):
+ def _connectUpgradedExtruderStacksToMachines(self) -> None:
extruder_stacks = self.findContainers(container_type = ExtruderStack.ExtruderStack)
for extruder_stack in extruder_stacks:
if extruder_stack.getNextStack():
diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py
index 042b065226..1455e140a8 100755
--- a/cura/Settings/CuraContainerStack.py
+++ b/cura/Settings/CuraContainerStack.py
@@ -87,6 +87,19 @@ class CuraContainerStack(ContainerStack):
def qualityChanges(self) -> InstanceContainer:
return cast(InstanceContainer, self._containers[_ContainerIndexes.QualityChanges])
+ ## Set the intent container.
+ #
+ # \param new_intent The new intent container. It is expected to have a "type" metadata entry with the value "intent".
+ def setIntent(self, new_intent: InstanceContainer, postpone_emit: bool = False) -> None:
+ self.replaceContainer(_ContainerIndexes.Intent, new_intent, postpone_emit = postpone_emit)
+
+ ## Get the quality container.
+ #
+ # \return The intent container. Should always be a valid container, but can be equal to the empty InstanceContainer.
+ @pyqtProperty(InstanceContainer, fset = setIntent, notify = pyqtContainersChanged)
+ def intent(self) -> InstanceContainer:
+ return cast(InstanceContainer, self._containers[_ContainerIndexes.Intent])
+
## Set the quality container.
#
# \param new_quality The new quality container. It is expected to have a "type" metadata entry with the value "quality".
@@ -330,16 +343,18 @@ class CuraContainerStack(ContainerStack):
class _ContainerIndexes:
UserChanges = 0
QualityChanges = 1
- Quality = 2
- Material = 3
- Variant = 4
- DefinitionChanges = 5
- Definition = 6
+ Intent = 2
+ Quality = 3
+ Material = 4
+ Variant = 5
+ DefinitionChanges = 6
+ Definition = 7
# Simple hash map to map from index to "type" metadata entry
IndexTypeMap = {
UserChanges: "user",
QualityChanges: "quality_changes",
+ Intent: "intent",
Quality: "quality",
Material: "material",
Variant: "variant",
diff --git a/cura/Settings/CuraFormulaFunctions.py b/cura/Settings/CuraFormulaFunctions.py
index 9ef80bd3d4..b35069da6f 100644
--- a/cura/Settings/CuraFormulaFunctions.py
+++ b/cura/Settings/CuraFormulaFunctions.py
@@ -40,9 +40,16 @@ class CuraFormulaFunctions:
global_stack = machine_manager.activeMachine
try:
- extruder_stack = global_stack.extruders[str(extruder_position)]
- except KeyError:
- Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available" % (property_key, extruder_position))
+ extruder_stack = global_stack.extruderList[int(extruder_position)]
+ except IndexError:
+ if extruder_position != 0:
+ Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. Returning the result form extruder 0 instead" % (property_key, extruder_position))
+ # This fixes a very specific fringe case; If a profile was created for a custom printer and one of the
+ # extruder settings has been set to non zero and the profile is loaded for a machine that has only a single extruder
+ # it would cause all kinds of issues (and eventually a crash).
+ # See https://github.com/Ultimaker/Cura/issues/5535
+ return self.getValueInExtruder(0, property_key, context)
+ Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. " % (property_key, extruder_position))
return None
value = extruder_stack.getRawProperty(property_key, "value", context = context)
@@ -97,11 +104,14 @@ class CuraFormulaFunctions:
machine_manager = self._application.getMachineManager()
global_stack = machine_manager.activeMachine
- extruder_stack = global_stack.extruders[str(extruder_position)]
+ try:
+ extruder_stack = global_stack.extruderList[extruder_position]
+ except IndexError:
+ Logger.log("w", "Unable to find extruder on in index %s", extruder_position)
+ else:
+ context = self.createContextForDefaultValueEvaluation(extruder_stack)
- context = self.createContextForDefaultValueEvaluation(extruder_stack)
-
- return self.getValueInExtruder(extruder_position, property_key, context = context)
+ return self.getValueInExtruder(extruder_position, property_key, context = context)
# Gets all default setting values as a list from all extruders of the currently active machine.
# The default values are those excluding the values in the user_changes container.
diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py
index c98c63f529..61a04e1be6 100644
--- a/cura/Settings/CuraStackBuilder.py
+++ b/cura/Settings/CuraStackBuilder.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
@@ -8,7 +8,8 @@ from UM.Logger import Logger
from UM.Settings.Interfaces import DefinitionContainerInterface
from UM.Settings.InstanceContainer import InstanceContainer
-from cura.Machines.VariantType import VariantType
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Machines.MachineNode import MachineNode
from .GlobalStack import GlobalStack
from .ExtruderStack import ExtruderStack
@@ -26,9 +27,8 @@ class CuraStackBuilder:
def createMachine(cls, name: str, definition_id: str) -> Optional[GlobalStack]:
from cura.CuraApplication import CuraApplication
application = CuraApplication.getInstance()
- variant_manager = application.getVariantManager()
- quality_manager = application.getQualityManager()
registry = application.getContainerRegistry()
+ container_tree = ContainerTree.getInstance()
definitions = registry.findDefinitionContainers(id = definition_id)
if not definitions:
@@ -37,14 +37,7 @@ class CuraStackBuilder:
return None
machine_definition = definitions[0]
-
- # get variant container for the global stack
- global_variant_container = application.empty_variant_container
- global_variant_node = variant_manager.getDefaultVariantNode(machine_definition, VariantType.BUILD_PLATE)
- if global_variant_node:
- global_variant_container = global_variant_node.getContainer()
- if not global_variant_container:
- global_variant_container = application.empty_variant_container
+ machine_node = container_tree.machines[machine_definition.getId()]
generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName())
# Make sure the new name does not collide with any definition or (quality) profile
@@ -56,9 +49,9 @@ class CuraStackBuilder:
new_global_stack = cls.createGlobalStack(
new_stack_id = generated_name,
definition = machine_definition,
- variant_container = global_variant_container,
+ variant_container = application.empty_variant_container,
material_container = application.empty_material_container,
- quality_container = application.empty_quality_container,
+ quality_container = machine_node.preferredGlobalQuality().container,
)
new_global_stack.setName(generated_name)
@@ -67,33 +60,9 @@ class CuraStackBuilder:
for position in extruder_dict:
cls.createExtruderStackWithDefaultSetup(new_global_stack, position)
- for new_extruder in new_global_stack.extruders.values(): #Only register the extruders if we're sure that all of them are correct.
+ for new_extruder in new_global_stack.extruders.values(): # Only register the extruders if we're sure that all of them are correct.
registry.addContainer(new_extruder)
- preferred_quality_type = machine_definition.getMetaDataEntry("preferred_quality_type")
- quality_group_dict = quality_manager.getQualityGroups(new_global_stack)
- if not quality_group_dict:
- # There is no available quality group, set all quality containers to empty.
- new_global_stack.quality = application.empty_quality_container
- for extruder_stack in new_global_stack.extruders.values():
- extruder_stack.quality = application.empty_quality_container
- else:
- # Set the quality containers to the preferred quality type if available, otherwise use the first quality
- # type that's available.
- if preferred_quality_type not in quality_group_dict:
- Logger.log("w", "The preferred quality {quality_type} doesn't exist for this set-up. Choosing a random one.".format(quality_type = preferred_quality_type))
- preferred_quality_type = next(iter(quality_group_dict))
- quality_group = quality_group_dict.get(preferred_quality_type)
-
- new_global_stack.quality = quality_group.node_for_global.getContainer()
- if not new_global_stack.quality:
- new_global_stack.quality = application.empty_quality_container
- for position, extruder_stack in new_global_stack.extruders.items():
- if position in quality_group.nodes_for_extruders and quality_group.nodes_for_extruders[position].getContainer():
- extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer()
- else:
- extruder_stack.quality = application.empty_quality_container
-
# Register the global stack after the extruder stacks are created. This prevents the registry from adding another
# extruder stack because the global stack didn't have one yet (which is enforced since Cura 3.1).
registry.addContainer(new_global_stack)
@@ -108,31 +77,32 @@ class CuraStackBuilder:
def createExtruderStackWithDefaultSetup(cls, global_stack: "GlobalStack", extruder_position: int) -> None:
from cura.CuraApplication import CuraApplication
application = CuraApplication.getInstance()
- variant_manager = application.getVariantManager()
- material_manager = application.getMaterialManager()
registry = application.getContainerRegistry()
- # get variant container for extruders
- extruder_variant_container = application.empty_variant_container
- extruder_variant_node = variant_manager.getDefaultVariantNode(global_stack.definition, VariantType.NOZZLE,
- global_stack = global_stack)
- extruder_variant_name = None
- if extruder_variant_node:
- extruder_variant_container = extruder_variant_node.getContainer()
- if not extruder_variant_container:
- extruder_variant_container = application.empty_variant_container
- extruder_variant_name = extruder_variant_container.getName()
-
+ # Get the extruder definition.
extruder_definition_dict = global_stack.getMetaDataEntry("machine_extruder_trains")
extruder_definition_id = extruder_definition_dict[str(extruder_position)]
- extruder_definition = registry.findDefinitionContainers(id = extruder_definition_id)[0]
+ try:
+ extruder_definition = registry.findDefinitionContainers(id = extruder_definition_id)[0]
+ except IndexError:
+ # It still needs to break, but we want to know what extruder ID made it break.
+ msg = "Unable to find extruder definition with the id [%s]" % extruder_definition_id
+ Logger.logException("e", msg)
+ raise IndexError(msg)
- # get material container for extruders
- material_container = application.empty_material_container
- material_node = material_manager.getDefaultMaterial(global_stack, str(extruder_position), extruder_variant_name,
- extruder_definition = extruder_definition)
- if material_node and material_node.getContainer():
- material_container = material_node.getContainer()
+ # Find out what filament diameter we need.
+ approximate_diameter = round(extruder_definition.getProperty("material_diameter", "value")) # Can't be modified by definition changes since we are just initialising the stack here.
+
+ # Find the preferred containers.
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
+ extruder_variant_node = machine_node.variants.get(machine_node.preferred_variant_name)
+ if not extruder_variant_node:
+ Logger.log("w", "Could not find preferred nozzle {nozzle_name}. Falling back to {fallback}.".format(nozzle_name = machine_node.preferred_variant_name, fallback = next(iter(machine_node.variants))))
+ extruder_variant_node = next(iter(machine_node.variants.values()))
+ extruder_variant_container = extruder_variant_node.container
+ material_node = extruder_variant_node.preferredMaterial(approximate_diameter)
+ material_container = material_node.container
+ quality_node = material_node.preferredQuality()
new_extruder_id = registry.uniqueName(extruder_definition_id)
new_extruder = cls.createExtruderStack(
@@ -142,7 +112,7 @@ class CuraStackBuilder:
position = extruder_position,
variant_container = extruder_variant_container,
material_container = material_container,
- quality_container = application.empty_quality_container
+ quality_container = quality_node.container
)
new_extruder.setNextStack(global_stack)
@@ -184,6 +154,7 @@ class CuraStackBuilder:
stack.variant = variant_container
stack.material = material_container
stack.quality = quality_container
+ stack.intent = application.empty_intent_container
stack.qualityChanges = application.empty_quality_changes_container
stack.userChanges = user_container
@@ -232,6 +203,7 @@ class CuraStackBuilder:
stack.variant = variant_container
stack.material = material_container
stack.quality = quality_container
+ stack.intent = application.empty_intent_container
stack.qualityChanges = application.empty_quality_changes_container
stack.userChanges = user_container
diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py
index b6b7b31936..62bf396878 100755
--- a/cura/Settings/ExtruderManager.py
+++ b/cura/Settings/ExtruderManager.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant # For communicating data and events to Qt.
@@ -12,7 +12,6 @@ from UM.Scene.SceneNode import SceneNode
from UM.Scene.Selection import Selection
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.Settings.ContainerRegistry import ContainerRegistry # Finding containers by ID.
-from UM.Settings.ContainerStack import ContainerStack
from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING, Union
@@ -42,8 +41,6 @@ class ExtruderManager(QObject):
# TODO; I have no idea why this is a union of ID's and extruder stacks. This needs to be fixed at some point.
self._selected_object_extruders = [] # type: List[Union[str, "ExtruderStack"]]
- self._addCurrentMachineExtruders()
-
Selection.selectionChanged.connect(self.resetSelectedObjectExtruders)
## Signal to notify other components when the list of extruders for a machine definition changes.
@@ -74,7 +71,7 @@ class ExtruderManager(QObject):
global_container_stack = self._application.getGlobalContainerStack()
if global_container_stack:
- extruder_stack_ids = {position: extruder.id for position, extruder in global_container_stack.extruders.items()}
+ extruder_stack_ids = {extruder.getMetaDataEntry("position", ""): extruder.id for extruder in global_container_stack.extruderList}
return extruder_stack_ids
@@ -91,16 +88,6 @@ class ExtruderManager(QObject):
def activeExtruderIndex(self) -> int:
return self._active_extruder_index
- ## Gets the extruder name of an extruder of the currently active machine.
- #
- # \param index The index of the extruder whose name to get.
- @pyqtSlot(int, result = str)
- def getExtruderName(self, index: int) -> str:
- try:
- return self.getActiveExtruderStacks()[index].getName()
- except IndexError:
- return ""
-
## Emitted whenever the selectedObjectExtruders property changes.
selectedObjectExtrudersChanged = pyqtSignal()
@@ -114,7 +101,7 @@ class ExtruderManager(QObject):
selected_nodes = [] # type: List["SceneNode"]
for node in Selection.getAllSelectedObjects():
if node.callDecoration("isGroup"):
- for grouped_node in BreadthFirstIterator(node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for grouped_node in BreadthFirstIterator(node):
if grouped_node.callDecoration("isGroup"):
continue
@@ -131,7 +118,7 @@ class ExtruderManager(QObject):
elif current_extruder_trains:
object_extruders.add(current_extruder_trains[0].getId())
- self._selected_object_extruders = list(object_extruders) # type: List[Union[str, "ExtruderStack"]]
+ self._selected_object_extruders = list(object_extruders)
return self._selected_object_extruders
@@ -140,7 +127,7 @@ class ExtruderManager(QObject):
# This will trigger a recalculation of the extruders used for the
# selection.
def resetSelectedObjectExtruders(self) -> None:
- self._selected_object_extruders = [] # type: List[Union[str, "ExtruderStack"]]
+ self._selected_object_extruders = []
self.selectedObjectExtrudersChanged.emit()
@pyqtSlot(result = QObject)
@@ -180,7 +167,7 @@ class ExtruderManager(QObject):
# \param setting_key \type{str} The setting to get the property of.
# \param property \type{str} The property to get.
# \return \type{List} the list of results
- def getAllExtruderSettings(self, setting_key: str, prop: str) -> List:
+ def getAllExtruderSettings(self, setting_key: str, prop: str) -> List[Any]:
result = []
for extruder_stack in self.getActiveExtruderStacks():
@@ -205,7 +192,7 @@ class ExtruderManager(QObject):
# list.
#
# \return A list of extruder stacks.
- def getUsedExtruderStacks(self) -> List["ContainerStack"]:
+ def getUsedExtruderStacks(self) -> List["ExtruderStack"]:
global_stack = self._application.getGlobalContainerStack()
container_registry = ContainerRegistry.getInstance()
@@ -224,7 +211,16 @@ class ExtruderManager(QObject):
# Get the extruders of all printable meshes in the scene
meshes = [node for node in DepthFirstIterator(scene_root) if isinstance(node, SceneNode) and node.isSelectable()] #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+
+ # Exclude anti-overhang meshes
+ mesh_list = []
for mesh in meshes:
+ stack = mesh.callDecoration("getStack")
+ if stack is not None and (stack.getProperty("anti_overhang_mesh", "value") or stack.getProperty("support_mesh", "value")):
+ continue
+ mesh_list.append(mesh)
+
+ for mesh in mesh_list:
extruder_stack_id = mesh.callDecoration("getActiveExtruder")
if not extruder_stack_id:
# No per-object settings for this node
@@ -270,7 +266,8 @@ class ExtruderManager(QObject):
extruder_str_nr = str(global_stack.getProperty("adhesion_extruder_nr", "value"))
if extruder_str_nr == "-1":
extruder_str_nr = self._application.getMachineManager().defaultExtruderPosition
- used_extruder_stack_ids.add(self.extruderIds[extruder_str_nr])
+ if extruder_str_nr in self.extruderIds:
+ used_extruder_stack_ids.add(self.extruderIds[extruder_str_nr])
try:
return [container_registry.findContainerStacks(id = stack_id)[0] for stack_id in used_extruder_stack_ids]
@@ -311,48 +308,47 @@ class ExtruderManager(QObject):
self.resetSelectedObjectExtruders()
- ## Adds the extruders of the currently active machine.
- def _addCurrentMachineExtruders(self) -> None:
- global_stack = self._application.getGlobalContainerStack()
+ ## Adds the extruders to the selected machine.
+ def addMachineExtruders(self, global_stack: GlobalStack) -> None:
extruders_changed = False
+ container_registry = ContainerRegistry.getInstance()
+ global_stack_id = global_stack.getId()
- if global_stack:
- container_registry = ContainerRegistry.getInstance()
- global_stack_id = global_stack.getId()
+ # Gets the extruder trains that we just created as well as any that still existed.
+ extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = global_stack_id)
- # Gets the extruder trains that we just created as well as any that still existed.
- extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = global_stack_id)
+ # Make sure the extruder trains for the new machine can be placed in the set of sets
+ if global_stack_id not in self._extruder_trains:
+ self._extruder_trains[global_stack_id] = {}
+ extruders_changed = True
- # Make sure the extruder trains for the new machine can be placed in the set of sets
- if global_stack_id not in self._extruder_trains:
- self._extruder_trains[global_stack_id] = {}
- extruders_changed = True
+ # Register the extruder trains by position
+ for extruder_train in extruder_trains:
+ extruder_position = extruder_train.getMetaDataEntry("position")
+ self._extruder_trains[global_stack_id][extruder_position] = extruder_train
- # Register the extruder trains by position
- for extruder_train in extruder_trains:
- extruder_position = extruder_train.getMetaDataEntry("position")
- self._extruder_trains[global_stack_id][extruder_position] = extruder_train
+ # regardless of what the next stack is, we have to set it again, because of signal routing. ???
+ extruder_train.setParent(global_stack)
+ extruder_train.setNextStack(global_stack)
+ extruders_changed = True
- # regardless of what the next stack is, we have to set it again, because of signal routing. ???
- extruder_train.setParent(global_stack)
- extruder_train.setNextStack(global_stack)
- extruders_changed = True
-
- self.fixSingleExtrusionMachineExtruderDefinition(global_stack)
- if extruders_changed:
- self.extrudersChanged.emit(global_stack_id)
- self.setActiveExtruderIndex(0)
- self.activeExtruderChanged.emit()
+ self.fixSingleExtrusionMachineExtruderDefinition(global_stack)
+ if extruders_changed:
+ self.extrudersChanged.emit(global_stack_id)
# After 3.4, all single-extrusion machines have their own extruder definition files instead of reusing
# "fdmextruder". We need to check a machine here so its extruder definition is correct according to this.
def fixSingleExtrusionMachineExtruderDefinition(self, global_stack: "GlobalStack") -> None:
container_registry = ContainerRegistry.getInstance()
expected_extruder_definition_0_id = global_stack.getMetaDataEntry("machine_extruder_trains")["0"]
- extruder_stack_0 = global_stack.extruders.get("0")
+ try:
+ extruder_stack_0 = global_stack.extruderList[0]
+ except IndexError:
+ extruder_stack_0 = None
+
# At this point, extruder stacks for this machine may not have been loaded yet. In this case, need to look in
# the container registry as well.
- if not global_stack.extruders:
+ if not global_stack.extruderList:
extruder_trains = container_registry.findContainerStacks(type = "extruder_train",
machine = global_stack.getId())
if extruder_trains:
@@ -370,7 +366,13 @@ class ExtruderManager(QObject):
elif extruder_stack_0.definition.getId() != expected_extruder_definition_0_id:
Logger.log("e", "Single extruder printer [{printer}] expected extruder [{expected}], but got [{got}]. I'm making it [{expected}].".format(
printer = global_stack.getId(), expected = expected_extruder_definition_0_id, got = extruder_stack_0.definition.getId()))
- extruder_definition = container_registry.findDefinitionContainers(id = expected_extruder_definition_0_id)[0]
+ try:
+ extruder_definition = container_registry.findDefinitionContainers(id = expected_extruder_definition_0_id)[0]
+ except IndexError:
+ # It still needs to break, but we want to know what extruder ID made it break.
+ msg = "Unable to find extruder definition with the id [%s]" % expected_extruder_definition_0_id
+ Logger.logException("e", msg)
+ raise IndexError(msg)
extruder_stack_0.definition = extruder_definition
## Get all extruder values for a certain setting.
diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py
index edb0e7d41f..5d4b3e38b1 100644
--- a/cura/Settings/ExtruderStack.py
+++ b/cura/Settings/ExtruderStack.py
@@ -51,6 +51,10 @@ class ExtruderStack(CuraContainerStack):
def getNextStack(self) -> Optional["GlobalStack"]:
return super().getNextStack()
+ @pyqtProperty(int, constant = True)
+ def position(self) -> int:
+ return int(self.getMetaDataEntry("position"))
+
def setEnabled(self, enabled: bool) -> None:
if self.getMetaDataEntry("enabled", True) == enabled: # No change.
return # Don't emit a signal then.
@@ -135,12 +139,15 @@ class ExtruderStack(CuraContainerStack):
if limit_to_extruder == -1:
limit_to_extruder = int(cura.CuraApplication.CuraApplication.getInstance().getMachineManager().defaultExtruderPosition)
limit_to_extruder = str(limit_to_extruder)
+
if (limit_to_extruder is not None and limit_to_extruder != "-1") and self.getMetaDataEntry("position") != str(limit_to_extruder):
- if str(limit_to_extruder) in self.getNextStack().extruders:
- result = self.getNextStack().extruders[str(limit_to_extruder)].getProperty(key, property_name, context)
+ try:
+ result = self.getNextStack().extruderList[int(limit_to_extruder)].getProperty(key, property_name, context)
if result is not None:
context.popContainer()
return result
+ except IndexError:
+ pass
result = super().getProperty(key, property_name, context)
context.popContainer()
diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py
index 3940af7ecc..d3a8842aa3 100755
--- a/cura/Settings/GlobalStack.py
+++ b/cura/Settings/GlobalStack.py
@@ -1,12 +1,14 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from collections import defaultdict
import threading
from typing import Any, Dict, Optional, Set, TYPE_CHECKING, List
+import uuid
+
from PyQt5.QtCore import pyqtProperty, pyqtSlot, pyqtSignal
-from UM.Decorators import override
+from UM.Decorators import deprecated, override
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.SettingInstance import InstanceState
@@ -18,6 +20,7 @@ from UM.Platform import Platform
from UM.Util import parseBool
import cura.CuraApplication
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from . import Exceptions
from .CuraContainerStack import CuraContainerStack
@@ -34,6 +37,12 @@ class GlobalStack(CuraContainerStack):
self.setMetaDataEntry("type", "machine") # For backward compatibility
+ # TL;DR: If Cura is looking for printers that belong to the same group, it should use "group_id".
+ # Each GlobalStack by default belongs to a group which is identified via "group_id". This group_id is used to
+ # figure out which GlobalStacks are in the printer cluster for example without knowing the implementation
+ # details such as the um_network_key or some other identifier that's used by the underlying device plugin.
+ self.setMetaDataEntry("group_id", str(uuid.uuid4())) # Assign a new GlobalStack to a unique group by default
+
self._extruders = {} # type: Dict[str, "ExtruderStack"]
# This property is used to track which settings we are calculating the "resolve" for
@@ -53,17 +62,26 @@ class GlobalStack(CuraContainerStack):
#
# \return The extruders registered with this stack.
@pyqtProperty("QVariantMap", notify = extrudersChanged)
+ @deprecated("Please use extruderList instead.", "4.4")
def extruders(self) -> Dict[str, "ExtruderStack"]:
return self._extruders
@pyqtProperty("QVariantList", notify = extrudersChanged)
def extruderList(self) -> List["ExtruderStack"]:
- result_tuple_list = sorted(list(self.extruders.items()), key=lambda x: int(x[0]))
+ result_tuple_list = sorted(list(self._extruders.items()), key=lambda x: int(x[0]))
result_list = [item[1] for item in result_tuple_list]
machine_extruder_count = self.getProperty("machine_extruder_count", "value")
return result_list[:machine_extruder_count]
+ @pyqtProperty(int, constant = True)
+ def maxExtruderCount(self):
+ return len(self.getMetaDataEntry("machine_extruder_trains"))
+
+ @pyqtProperty(bool, notify=configuredConnectionTypesChanged)
+ def supportsNetworkConnection(self):
+ return self.getMetaDataEntry("supports_network_connection", False)
+
@classmethod
def getLoadingPriority(cls) -> int:
return 2
@@ -81,7 +99,28 @@ class GlobalStack(CuraContainerStack):
# Requesting it from the metadata actually gets them as strings (as that's what you get from serializing).
# But we do want them returned as a list of ints (so the rest of the code can directly compare)
connection_types = self.getMetaDataEntry("connection_type", "").split(",")
- return [int(connection_type) for connection_type in connection_types if connection_type != ""]
+ result = []
+ for connection_type in connection_types:
+ if connection_type != "":
+ try:
+ result.append(int(connection_type))
+ except ValueError:
+ # We got invalid data, probably a None.
+ pass
+ return result
+
+ # Returns a boolean indicating if this machine has a remote connection. A machine is considered as remotely
+ # connected if its connection types contain one of the following values:
+ # - ConnectionType.NetworkConnection
+ # - ConnectionType.CloudConnection
+ @pyqtProperty(bool, notify = configuredConnectionTypesChanged)
+ def hasRemoteConnection(self) -> bool:
+ has_remote_connection = False
+
+ for connection_type in self.configuredConnectionTypes:
+ has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
+ ConnectionType.CloudConnection.value]
+ return has_remote_connection
## \sa configuredConnectionTypes
def addConfiguredConnectionType(self, connection_type: int) -> None:
@@ -94,7 +133,7 @@ class GlobalStack(CuraContainerStack):
## \sa configuredConnectionTypes
def removeConfiguredConnectionType(self, connection_type: int) -> None:
configured_connection_types = self.configuredConnectionTypes
- if connection_type in self.configured_connection_types:
+ if connection_type in configured_connection_types:
# Store the values as a string.
configured_connection_types.remove(connection_type)
self.setMetaDataEntry("connection_type", ",".join([str(c_type) for c_type in configured_connection_types]))
@@ -106,6 +145,14 @@ class GlobalStack(CuraContainerStack):
return "machine_stack"
return configuration_type
+ def getIntentCategory(self) -> str:
+ intent_category = "default"
+ for extruder in self.extruderList:
+ category = extruder.intent.getMetaDataEntry("intent_category", "default")
+ if category != "default" and category != intent_category:
+ intent_category = category
+ return intent_category
+
def getBuildplateName(self) -> Optional[str]:
name = None
if self.variant.getId() != "empty_variant":
@@ -200,7 +247,7 @@ class GlobalStack(CuraContainerStack):
# Determine whether or not we should try to get the "resolve" property instead of the
# requested property.
def _shouldResolve(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> bool:
- if property_name is not "value":
+ if property_name != "value":
# Do not try to resolve anything but the "value" property
return False
@@ -240,14 +287,17 @@ class GlobalStack(CuraContainerStack):
def getHeadAndFansCoordinates(self):
return self.getProperty("machine_head_with_fans_polygon", "value")
- def getHasMaterials(self) -> bool:
+ @pyqtProperty(bool, constant = True)
+ def hasMaterials(self) -> bool:
return parseBool(self.getMetaDataEntry("has_materials", False))
- def getHasVariants(self) -> bool:
+ @pyqtProperty(bool, constant = True)
+ def hasVariants(self) -> bool:
return parseBool(self.getMetaDataEntry("has_variants", False))
- def getHasMachineQuality(self) -> bool:
- return parseBool(self.getMetaDataEntry("has_machine_quality", False))
+ @pyqtProperty(bool, constant = True)
+ def hasVariantBuildplates(self) -> bool:
+ return parseBool(self.getMetaDataEntry("has_variant_buildplates", False))
## Get default firmware file name if one is specified in the firmware
@pyqtSlot(result = str)
@@ -275,6 +325,17 @@ class GlobalStack(CuraContainerStack):
Logger.log("w", "Firmware file %s not found.", hex_file)
return ""
+ def getName(self) -> str:
+ return self._metadata.get("group_name", self._metadata.get("name", ""))
+
+ def setName(self, name: "str") -> None:
+ super().setName(name)
+
+ nameChanged = pyqtSignal()
+ name = pyqtProperty(str, fget=getName, fset=setName, notify=nameChanged)
+
+
+
## private:
global_stack_mime = MimeType(
name = "application/x-cura-globalstack",
diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py
new file mode 100644
index 0000000000..5133b401b4
--- /dev/null
+++ b/cura/Settings/IntentManager.py
@@ -0,0 +1,179 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot
+from typing import Any, Dict, List, Optional, Set, Tuple, TYPE_CHECKING
+
+from UM.Logger import Logger
+from UM.Settings.InstanceContainer import InstanceContainer
+
+import cura.CuraApplication
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Settings.cura_empty_instance_containers import empty_intent_container
+
+if TYPE_CHECKING:
+ from UM.Settings.InstanceContainer import InstanceContainer
+
+
+## Front-end for querying which intents are available for a certain
+# configuration.
+class IntentManager(QObject):
+ __instance = None
+
+ ## This class is a singleton.
+ @classmethod
+ def getInstance(cls):
+ if not cls.__instance:
+ cls.__instance = IntentManager()
+ return cls.__instance
+
+ intentCategoryChanged = pyqtSignal() #Triggered when we switch categories.
+
+ ## Gets the metadata dictionaries of all intent profiles for a given
+ # configuration.
+ #
+ # \param definition_id ID of the printer.
+ # \param nozzle_name Name of the nozzle.
+ # \param material_base_file The base_file of the material.
+ # \return A list of metadata dictionaries matching the search criteria, or
+ # an empty list if nothing was found.
+ def intentMetadatas(self, definition_id: str, nozzle_name: str, material_base_file: str) -> List[Dict[str, Any]]:
+ intent_metadatas = [] # type: List[Dict[str, Any]]
+ try:
+ materials = ContainerTree.getInstance().machines[definition_id].variants[nozzle_name].materials
+ except KeyError:
+ Logger.log("w", "Unable to find the machine %s or the variant %s", definition_id, nozzle_name)
+ materials = {}
+ if material_base_file not in materials:
+ return intent_metadatas
+
+ material_node = materials[material_base_file]
+ for quality_node in material_node.qualities.values():
+ for intent_node in quality_node.intents.values():
+ intent_metadatas.append(intent_node.getMetadata())
+ return intent_metadatas
+
+ ## Collects and returns all intent categories available for the given
+ # parameters. Note that the 'default' category is always available.
+ #
+ # \param definition_id ID of the printer.
+ # \param nozzle_name Name of the nozzle.
+ # \param material_id ID of the material.
+ # \return A set of intent category names.
+ def intentCategories(self, definition_id: str, nozzle_id: str, material_id: str) -> List[str]:
+ categories = set()
+ for intent in self.intentMetadatas(definition_id, nozzle_id, material_id):
+ categories.add(intent["intent_category"])
+ categories.add("default") #The "empty" intent is not an actual profile specific to the configuration but we do want it to appear in the categories list.
+ return list(categories)
+
+ ## List of intents to be displayed in the interface.
+ #
+ # For the interface this will have to be broken up into the different
+ # intent categories. That is up to the model there.
+ #
+ # \return A list of tuples of intent_category and quality_type. The actual
+ # instance may vary per extruder.
+ def getCurrentAvailableIntents(self) -> List[Tuple[str, str]]:
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ global_stack = application.getGlobalContainerStack()
+ if global_stack is None:
+ return [("default", "normal")]
+ # TODO: We now do this (return a default) if the global stack is missing, but not in the code below,
+ # even though there should always be defaults. The problem then is what to do with the quality_types.
+ # Currently _also_ inconsistent with 'currentAvailableIntentCategories', which _does_ return default.
+ quality_groups = ContainerTree.getInstance().getCurrentQualityGroups()
+ available_quality_types = {quality_group.quality_type for quality_group in quality_groups.values() if quality_group.node_for_global is not None}
+
+ final_intent_ids = set() # type: Set[str]
+ current_definition_id = global_stack.definition.getId()
+ for extruder_stack in global_stack.extruderList:
+ if not extruder_stack.isEnabled:
+ continue
+ nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
+ material_id = extruder_stack.material.getMetaDataEntry("base_file")
+ final_intent_ids |= {metadata["id"] for metadata in self.intentMetadatas(current_definition_id, nozzle_name, material_id) if metadata.get("quality_type") in available_quality_types}
+
+ result = set() # type: Set[Tuple[str, str]]
+ for intent_id in final_intent_ids:
+ intent_metadata = application.getContainerRegistry().findContainersMetadata(id = intent_id)[0]
+ result.add((intent_metadata["intent_category"], intent_metadata["quality_type"]))
+ return list(result)
+
+ ## List of intent categories available in either of the extruders.
+ #
+ # This is purposefully inconsistent with the way that the quality types
+ # are listed. The quality types will show all quality types available in
+ # the printer using any configuration. This will only list the intent
+ # categories that are available using the current configuration (but the
+ # union over the extruders).
+ # \return List of all categories in the current configurations of all
+ # extruders.
+ def currentAvailableIntentCategories(self) -> List[str]:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return ["default"]
+ current_definition_id = global_stack.definition.getId()
+ final_intent_categories = set() # type: Set[str]
+ for extruder_stack in global_stack.extruderList:
+ if not extruder_stack.isEnabled:
+ continue
+ nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
+ material_id = extruder_stack.material.getMetaDataEntry("base_file")
+ final_intent_categories.update(self.intentCategories(current_definition_id, nozzle_name, material_id))
+ return list(final_intent_categories)
+
+ ## The intent that gets selected by default when no intent is available for
+ # the configuration, an extruder can't match the intent that the user
+ # selects, or just when creating a new printer.
+ def getDefaultIntent(self) -> "InstanceContainer":
+ return empty_intent_container
+
+ @pyqtProperty(str, notify = intentCategoryChanged)
+ def currentIntentCategory(self) -> str:
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ active_extruder_stack = application.getMachineManager().activeStack
+ if active_extruder_stack is None:
+ return ""
+ return active_extruder_stack.intent.getMetaDataEntry("intent_category", "")
+
+ ## Apply intent on the stacks.
+ @pyqtSlot(str, str)
+ def selectIntent(self, intent_category: str, quality_type: str) -> None:
+ Logger.log("i", "Attempting to set intent_category to [%s] and quality type to [%s]", intent_category, quality_type)
+ old_intent_category = self.currentIntentCategory
+ application = cura.CuraApplication.CuraApplication.getInstance()
+ global_stack = application.getGlobalContainerStack()
+ if global_stack is None:
+ return
+ current_definition_id = global_stack.definition.getId()
+ machine_node = ContainerTree.getInstance().machines[current_definition_id]
+ for extruder_stack in global_stack.extruderList:
+ nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
+ material_id = extruder_stack.material.getMetaDataEntry("base_file")
+
+ material_node = machine_node.variants[nozzle_name].materials[material_id]
+
+ # Since we want to switch to a certain quality type, check the tree if we have one.
+ quality_node = None
+ for q_node in material_node.qualities.values():
+ if q_node.quality_type == quality_type:
+ quality_node = q_node
+
+ if quality_node is None:
+ Logger.log("w", "Unable to find quality_type [%s] for extruder [%s]", quality_type, extruder_stack.getId())
+ continue
+
+ # Check that quality node if we can find a matching intent.
+ intent_id = None
+ for id, intent_node in quality_node.intents.items():
+ if intent_node.intent_category == intent_category:
+ intent_id = id
+ intent = application.getContainerRegistry().findContainers(id = intent_id)
+ if intent:
+ extruder_stack.intent = intent[0]
+ else:
+ extruder_stack.intent = self.getDefaultIntent()
+ application.getMachineManager().setQualityGroupByQualityType(quality_type)
+ if old_intent_category != intent_category:
+ self.intentCategoryChanged.emit()
diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py
index 25eef60268..de6e270a86 100755
--- a/cura/Settings/MachineManager.py
+++ b/cura/Settings/MachineManager.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import time
@@ -6,13 +6,14 @@ import re
import unicodedata
from typing import Any, List, Dict, TYPE_CHECKING, Optional, cast
+from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer
+
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
+from UM.Decorators import deprecated
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.Interfaces import ContainerInterface
from UM.Signal import Signal
-
-from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer
from UM.FlameProfiler import pyqtSlot
from UM import Util
from UM.Logger import Logger
@@ -21,33 +22,34 @@ from UM.Message import Message
from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique
-from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
-from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionType
-from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
-from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
+import cura.CuraApplication # Imported like this to prevent circular references.
+
+from cura.Machines.ContainerNode import ContainerNode
+from cura.Machines.ContainerTree import ContainerTree
+from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel
+
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionType
+from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
+from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
+from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.ExtruderStack import ExtruderStack
from cura.Settings.cura_empty_instance_containers import (empty_definition_changes_container, empty_variant_container,
empty_material_container, empty_quality_container,
- empty_quality_changes_container)
+ empty_quality_changes_container, empty_intent_container)
from .CuraStackBuilder import CuraStackBuilder
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
-
+from cura.Settings.GlobalStack import GlobalStack
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
- from cura.Settings.CuraContainerStack import CuraContainerStack
- from cura.Settings.GlobalStack import GlobalStack
- from cura.Machines.MaterialManager import MaterialManager
- from cura.Machines.QualityManager import QualityManager
- from cura.Machines.VariantManager import VariantManager
- from cura.Machines.ContainerNode import ContainerNode
+ from cura.Machines.MaterialNode import MaterialNode
from cura.Machines.QualityChangesGroup import QualityChangesGroup
from cura.Machines.QualityGroup import QualityGroup
+ from cura.Machines.VariantNode import VariantNode
class MachineManager(QObject):
@@ -58,8 +60,6 @@ class MachineManager(QObject):
self._global_container_stack = None # type: Optional[GlobalStack]
self._current_root_material_id = {} # type: Dict[str, str]
- self._current_quality_group = None # type: Optional[QualityGroup]
- self._current_quality_changes_group = None # type: Optional[QualityChangesGroup]
self._default_extruder_position = "0" # to be updated when extruders are switched on and off
@@ -95,7 +95,6 @@ class MachineManager(QObject):
extruder_manager.activeExtruderChanged.connect(self.activeQualityChanged)
self.globalContainerChanged.connect(self.activeStackChanged)
- self.globalValueChanged.connect(self.activeStackValueChanged)
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged)
self.activeStackChanged.connect(self.activeStackValueChanged)
@@ -106,7 +105,7 @@ class MachineManager(QObject):
# There might already be some output devices by the time the signal is connected
self._onOutputDevicesChanged()
- self._current_printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
+ self._current_printer_configuration = PrinterConfigurationModel() # Indicates the current configuration setup in this printer
self.activeMaterialChanged.connect(self._onCurrentConfigurationChanged)
self.activeVariantChanged.connect(self._onCurrentConfigurationChanged)
# Force to compute the current configuration
@@ -118,22 +117,20 @@ class MachineManager(QObject):
if containers:
containers[0].nameChanged.connect(self._onMaterialNameChanged)
- self._material_manager = self._application.getMaterialManager() # type: MaterialManager
- self._variant_manager = self._application.getVariantManager() # type: VariantManager
- self._quality_manager = self._application.getQualityManager() # type: QualityManager
-
- # When the materials lookup table gets updated, it can mean that a material has its name changed, which should
- # be reflected on the GUI. This signal emission makes sure that it happens.
- self._material_manager.materialsUpdated.connect(self.rootMaterialChanged)
- # When the materials get updated, it can be that an activated material's diameter gets changed. In that case,
- # a material update should be triggered to make sure that the machine still has compatible materials activated.
- self._material_manager.materialsUpdated.connect(self._updateUponMaterialMetadataChange)
self.rootMaterialChanged.connect(self._onRootMaterialChanged)
# Emit the printerConnectedStatusChanged when either globalContainerChanged or outputDevicesChanged are emitted
self.globalContainerChanged.connect(self.printerConnectedStatusChanged)
self.outputDevicesChanged.connect(self.printerConnectedStatusChanged)
+ # For updating active quality display name
+ self.activeQualityChanged.connect(self.activeQualityDisplayNameChanged)
+ self.activeIntentChanged.connect(self.activeQualityDisplayNameChanged)
+ self.activeQualityGroupChanged.connect(self.activeQualityDisplayNameChanged)
+ self.activeQualityChangesGroupChanged.connect(self.activeQualityDisplayNameChanged)
+
+ activeQualityDisplayNameChanged = pyqtSignal()
+
activeQualityGroupChanged = pyqtSignal()
activeQualityChangesGroupChanged = pyqtSignal()
@@ -141,10 +138,10 @@ class MachineManager(QObject):
activeMaterialChanged = pyqtSignal()
activeVariantChanged = pyqtSignal()
activeQualityChanged = pyqtSignal()
- activeStackChanged = pyqtSignal() # Emitted whenever the active stack is changed (ie: when changing between extruders, changing a profile, but not when changing a value)
- extruderChanged = pyqtSignal()
+ activeIntentChanged = pyqtSignal()
+ activeStackChanged = pyqtSignal() # Emitted whenever the active extruder stack is changed (ie: when switching the active extruder tab or changing between printers)
+ extruderChanged = pyqtSignal() # Emitted whenever an extruder is activated or deactivated or the default extruder changes.
- globalValueChanged = pyqtSignal() # Emitted whenever a value inside global container is changed.
activeStackValueChanged = pyqtSignal() # Emitted whenever a value inside the active stack is changed.
activeStackValidationChanged = pyqtSignal() # Emitted whenever a validation inside active container is changed
stacksValidationChanged = pyqtSignal() # Emitted whenever a validation is changed
@@ -171,10 +168,9 @@ class MachineManager(QObject):
self._printer_output_devices.append(printer_output_device)
self.outputDevicesChanged.emit()
- self.printerConnectedStatusChanged.emit()
@pyqtProperty(QObject, notify = currentConfigurationChanged)
- def currentConfiguration(self) -> ConfigurationModel:
+ def currentConfiguration(self) -> PrinterConfigurationModel:
return self._current_printer_configuration
def _onCurrentConfigurationChanged(self) -> None:
@@ -183,9 +179,11 @@ class MachineManager(QObject):
# Create the configuration model with the current data in Cura
self._current_printer_configuration.printerType = self._global_container_stack.definition.getName()
- self._current_printer_configuration.extruderConfigurations = []
- for extruder in self._global_container_stack.extruders.values():
- extruder_configuration = ExtruderConfigurationModel()
+
+ if len(self._current_printer_configuration.extruderConfigurations) != len(self._global_container_stack.extruderList):
+ self._current_printer_configuration.extruderConfigurations = [ExtruderConfigurationModel() for extruder in self._global_container_stack.extruderList]
+
+ for extruder, extruder_configuration in zip(self._global_container_stack.extruderList, self._current_printer_configuration.extruderConfigurations):
# For compare just the GUID is needed at this moment
mat_type = extruder.material.getMetaDataEntry("material") if extruder.material != empty_material_container else None
mat_guid = extruder.material.getMetaDataEntry("GUID") if extruder.material != empty_material_container else None
@@ -197,15 +195,15 @@ class MachineManager(QObject):
extruder_configuration.position = int(extruder.getMetaDataEntry("position"))
extruder_configuration.material = material_model
extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != empty_variant_container else None
- self._current_printer_configuration.extruderConfigurations.append(extruder_configuration)
# An empty build plate configuration from the network printer is presented as an empty string, so use "" for an
# empty build plate.
- self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != empty_variant_container else ""
+ self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value")\
+ if self._global_container_stack.variant != empty_variant_container else self._global_container_stack.getProperty("machine_buildplate_type", "default_value")
self.currentConfigurationChanged.emit()
@pyqtSlot(QObject, result = bool)
- def matchesConfiguration(self, configuration: ConfigurationModel) -> bool:
+ def matchesConfiguration(self, configuration: PrinterConfigurationModel) -> bool:
return self._current_printer_configuration == configuration
@pyqtProperty("QVariantList", notify = outputDevicesChanged)
@@ -219,12 +217,9 @@ class MachineManager(QObject):
return 0
return len(general_definition_containers[0].getAllKeys())
+ ## Triggered when the global container stack is changed in CuraApplication.
def _onGlobalContainerChanged(self) -> None:
if self._global_container_stack:
- try:
- self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged)
- except TypeError: # pyQtSignal gives a TypeError when disconnecting from something that was already disconnected.
- pass
try:
self._global_container_stack.containersChanged.disconnect(self._onContainersChanged)
except TypeError:
@@ -249,7 +244,6 @@ class MachineManager(QObject):
if self._global_container_stack:
self._application.getPreferences().setValue("cura/active_machine", self._global_container_stack.getId())
- self._global_container_stack.nameChanged.connect(self._onMachineNameChanged)
self._global_container_stack.containersChanged.connect(self._onContainersChanged)
self._global_container_stack.propertyChanged.connect(self._onPropertyChanged)
@@ -269,6 +263,8 @@ class MachineManager(QObject):
extruder_stack.propertyChanged.connect(self._onPropertyChanged)
extruder_stack.containersChanged.connect(self._onContainersChanged)
+ self._onRootMaterialChanged()
+
self.activeQualityGroupChanged.emit()
def _onActiveExtruderStackChanged(self) -> None:
@@ -279,6 +275,7 @@ class MachineManager(QObject):
self.activeQualityChanged.emit()
self.activeVariantChanged.emit()
self.activeMaterialChanged.emit()
+ self.activeIntentChanged.emit()
self.rootMaterialChanged.emit()
self.numberExtrudersEnabledChanged.emit()
@@ -291,84 +288,39 @@ class MachineManager(QObject):
# Notify UI items, such as the "changed" star in profile pull down menu.
self.activeStackValueChanged.emit()
- ## Given a global_stack, make sure that it's all valid by searching for this quality group and applying it again
- def _initMachineState(self, global_stack: "CuraContainerStack") -> None:
- material_dict = {}
- for position, extruder in global_stack.extruders.items():
- material_dict[position] = extruder.material.getMetaDataEntry("base_file")
- self._current_root_material_id = material_dict
-
- # Update materials to make sure that the diameters match with the machine's
- for position in global_stack.extruders:
- self.updateMaterialWithVariant(position)
-
- global_quality = global_stack.quality
- quality_type = global_quality.getMetaDataEntry("quality_type")
- global_quality_changes = global_stack.qualityChanges
- global_quality_changes_name = global_quality_changes.getName()
-
- # Try to set the same quality/quality_changes as the machine specified.
- # If the quality/quality_changes is not available, switch to the default or the first quality that's available.
- same_quality_found = False
- quality_groups = self._application.getQualityManager().getQualityGroups(global_stack)
-
- if global_quality_changes.getId() != "empty_quality_changes":
- quality_changes_groups = self._application.getQualityManager().getQualityChangesGroups(global_stack)
- new_quality_changes_group = quality_changes_groups.get(global_quality_changes_name)
- if new_quality_changes_group is not None:
- self._setQualityChangesGroup(new_quality_changes_group)
- same_quality_found = True
- Logger.log("i", "Machine '%s' quality changes set to '%s'",
- global_stack.getName(), new_quality_changes_group.name)
- else:
- new_quality_group = quality_groups.get(quality_type)
- if new_quality_group is not None:
- self._setQualityGroup(new_quality_group, empty_quality_changes = True)
- same_quality_found = True
- Logger.log("i", "Machine '%s' quality set to '%s'",
- global_stack.getName(), new_quality_group.quality_type)
-
- # Could not find the specified quality/quality_changes, switch to the preferred quality if available,
- # otherwise the first quality that's available, otherwise empty (not supported).
- if not same_quality_found:
- Logger.log("i", "Machine '%s' could not find quality_type '%s' and quality_changes '%s'. "
- "Available quality types are [%s]. Switching to default quality.",
- global_stack.getName(), quality_type, global_quality_changes_name,
- ", ".join(quality_groups.keys()))
- preferred_quality_type = global_stack.getMetaDataEntry("preferred_quality_type")
- quality_group = quality_groups.get(preferred_quality_type)
- if quality_group is None:
- if quality_groups:
- quality_group = list(quality_groups.values())[0]
- self._setQualityGroup(quality_group, empty_quality_changes = True)
-
@pyqtSlot(str)
def setActiveMachine(self, stack_id: str) -> None:
self.blurSettings.emit() # Ensure no-one has focus.
container_registry = CuraContainerRegistry.getInstance()
-
containers = container_registry.findContainerStacks(id = stack_id)
if not containers:
return
- global_stack = containers[0]
+ global_stack = cast(GlobalStack, containers[0])
# Make sure that the default machine actions for this machine have been added
self._application.getMachineActionManager().addDefaultMachineActions(global_stack)
- ExtruderManager.getInstance().fixSingleExtrusionMachineExtruderDefinition(global_stack)
+ extruder_manager = ExtruderManager.getInstance()
+ extruder_manager.fixSingleExtrusionMachineExtruderDefinition(global_stack)
if not global_stack.isValid():
# Mark global stack as invalid
ConfigurationErrorMessage.getInstance().addFaultyContainers(global_stack.getId())
return # We're done here
- ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder
self._global_container_stack = global_stack
+ extruder_manager.addMachineExtruders(global_stack)
self._application.setGlobalContainerStack(global_stack)
- ExtruderManager.getInstance()._globalContainerStackChanged()
- self._initMachineState(global_stack)
- self._onGlobalContainerChanged()
+
+ # Switch to the first enabled extruder
+ self.updateDefaultExtruder()
+ default_extruder_position = int(self.defaultExtruderPosition)
+ old_active_extruder_index = extruder_manager.activeExtruderIndex
+ extruder_manager.setActiveExtruderIndex(default_extruder_position)
+ if old_active_extruder_index == default_extruder_position:
+ # This signal might not have been emitted yet (if it didn't change) but we still want the models to update that depend on it because we changed the contents of the containers too.
+ extruder_manager.activeExtruderChanged.emit()
self.__emitChangedSignals()
@@ -383,12 +335,21 @@ class MachineManager(QObject):
machines = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
for machine in machines:
if machine.definition.getId() == definition_id:
- return machine
+ return cast(GlobalStack, machine)
return None
+ @pyqtSlot(str)
@pyqtSlot(str, str)
- def addMachine(self, name: str, definition_id: str) -> None:
- new_stack = CuraStackBuilder.createMachine(name, definition_id)
+ def addMachine(self, definition_id: str, name: Optional[str] = None) -> None:
+ Logger.log("i", "Trying to add a machine with the definition id [%s]", definition_id)
+ if name is None:
+ definitions = CuraContainerRegistry.getInstance().findDefinitionContainers(id = definition_id)
+ if definitions:
+ name = definitions[0].getName()
+ else:
+ name = definition_id
+
+ new_stack = CuraStackBuilder.createMachine(cast(str, name), definition_id)
if new_stack:
# Instead of setting the global container stack here, we set the active machine and so the signals are emitted
self.setActiveMachine(new_stack.getId())
@@ -451,6 +412,7 @@ class MachineManager(QObject):
# \param key \type{str} the name of the key to delete
@pyqtSlot(str)
def clearUserSettingAllCurrentStacks(self, key: str) -> None:
+ Logger.log("i", "Clearing the setting [%s] from all stacks", key)
if not self._global_container_stack:
return
@@ -485,24 +447,6 @@ class MachineManager(QObject):
def stacksHaveErrors(self) -> bool:
return bool(self._stacks_have_errors)
- @pyqtProperty(str, notify = globalContainerChanged)
- def activeMachineDefinitionName(self) -> str:
- if self._global_container_stack:
- return self._global_container_stack.definition.getName()
- return ""
-
- @pyqtProperty(str, notify = globalContainerChanged)
- def activeMachineName(self) -> str:
- if self._global_container_stack:
- return self._global_container_stack.getMetaDataEntry("group_name", self._global_container_stack.getName())
- return ""
-
- @pyqtProperty(str, notify = globalContainerChanged)
- def activeMachineId(self) -> str:
- if self._global_container_stack:
- return self._global_container_stack.getId()
- return ""
-
@pyqtProperty(str, notify = globalContainerChanged)
def activeMachineFirmwareVersion(self) -> str:
if not self._printer_output_devices:
@@ -519,23 +463,6 @@ class MachineManager(QObject):
def printerConnected(self) -> bool:
return bool(self._printer_output_devices)
- @pyqtProperty(bool, notify = printerConnectedStatusChanged)
- def activeMachineHasRemoteConnection(self) -> bool:
- if self._global_container_stack:
- has_remote_connection = False
-
- for connection_type in self._global_container_stack.configuredConnectionTypes:
- has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
- ConnectionType.CloudConnection.value]
- return has_remote_connection
- return False
-
- @pyqtProperty("QVariantList", notify=globalContainerChanged)
- def activeMachineConfiguredConnectionTypes(self):
- if self._global_container_stack:
- return self._global_container_stack.configuredConnectionTypes
- return []
-
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineIsGroup(self) -> bool:
return bool(self._printer_output_devices) and len(self._printer_output_devices[0].printers) > 1
@@ -579,7 +506,7 @@ class MachineManager(QObject):
def activeStack(self) -> Optional["ExtruderStack"]:
return self._active_container_stack
- @pyqtProperty(str, notify=activeMaterialChanged)
+ @pyqtProperty(str, notify = activeMaterialChanged)
def activeMaterialId(self) -> str:
if self._active_container_stack:
material = self._active_container_stack.material
@@ -587,44 +514,20 @@ class MachineManager(QObject):
return material.getId()
return ""
- ## Gets a dict with the active materials ids set in all extruder stacks and the global stack
- # (when there is one extruder, the material is set in the global stack)
- #
- # \return The material ids in all stacks
- @pyqtProperty("QVariantMap", notify = activeMaterialChanged)
- def allActiveMaterialIds(self) -> Dict[str, str]:
- result = {}
-
- active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- for stack in active_stacks:
- material_container = stack.material
- if not material_container:
- continue
- result[stack.getId()] = material_container.getId()
-
- return result
-
## Gets the layer height of the currently active quality profile.
#
# This is indicated together with the name of the active quality profile.
#
# \return The layer height of the currently active quality profile. If
- # there is no quality profile, this returns 0.
+ # there is no quality profile, this returns the default layer height.
@pyqtProperty(float, notify = activeQualityGroupChanged)
def activeQualityLayerHeight(self) -> float:
if not self._global_container_stack:
return 0
- if self._current_quality_changes_group:
- value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.qualityChanges.getId())
- if isinstance(value, SettingFunction):
- value = value(self._global_container_stack)
- return value
- elif self._current_quality_group:
- value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.quality.getId())
- if isinstance(value, SettingFunction):
- value = value(self._global_container_stack)
- return value
- return 0
+ value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.qualityChanges.getId())
+ if isinstance(value, SettingFunction):
+ value = value(self._global_container_stack)
+ return value
@pyqtProperty(str, notify = activeVariantChanged)
def globalVariantName(self) -> str:
@@ -636,27 +539,57 @@ class MachineManager(QObject):
@pyqtProperty(str, notify = activeQualityGroupChanged)
def activeQualityType(self) -> str:
- quality_type = ""
- if self._active_container_stack:
- if self._current_quality_group:
- quality_type = self._current_quality_group.quality_type
- return quality_type
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack:
+ return ""
+ return global_stack.quality.getMetaDataEntry("quality_type")
@pyqtProperty(bool, notify = activeQualityGroupChanged)
def isActiveQualitySupported(self) -> bool:
- is_supported = False
- if self._global_container_stack:
- if self._current_quality_group:
- is_supported = self._current_quality_group.is_available
- return is_supported
+ global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_container_stack:
+ return False
+ active_quality_group = self.activeQualityGroup()
+ if active_quality_group is None:
+ return False
+ return active_quality_group.is_available
@pyqtProperty(bool, notify = activeQualityGroupChanged)
def isActiveQualityExperimental(self) -> bool:
- is_experimental = False
- if self._global_container_stack:
- if self._current_quality_group:
- is_experimental = self._current_quality_group.is_experimental
- return is_experimental
+ global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_container_stack:
+ return False
+ active_quality_group = self.activeQualityGroup()
+ if active_quality_group is None:
+ return False
+ return active_quality_group.is_experimental
+
+ @pyqtProperty(str, notify = activeIntentChanged)
+ def activeIntentCategory(self) -> str:
+ global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+
+ if not global_container_stack:
+ return ""
+ return global_container_stack.getIntentCategory()
+
+ # Provies a list of extruder positions that have a different intent from the active one.
+ @pyqtProperty("QStringList", notify=activeIntentChanged)
+ def extruderPositionsWithNonActiveIntent(self):
+ global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+
+ if not global_container_stack:
+ return []
+
+ active_intent_category = self.activeIntentCategory
+ result = []
+ for extruder in global_container_stack.extruderList:
+ if not extruder.isEnabled:
+ continue
+ category = extruder.intent.getMetaDataEntry("intent_category", "default")
+ if category != active_intent_category:
+ result.append(str(int(extruder.getMetaDataEntry("position")) + 1))
+
+ return result
## Returns whether there is anything unsupported in the current set-up.
#
@@ -667,7 +600,7 @@ class MachineManager(QObject):
def isCurrentSetupSupported(self) -> bool:
if not self._global_container_stack:
return False
- for stack in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
+ for stack in [self._global_container_stack] + self._global_container_stack.extruderList:
for container in stack.getContainers():
if not container:
return False
@@ -675,11 +608,6 @@ class MachineManager(QObject):
return False
return True
- ## Check if a container is read_only
- @pyqtSlot(str, result = bool)
- def isReadOnly(self, container_id: str) -> bool:
- return CuraContainerRegistry.getInstance().isReadOnly(container_id)
-
## Copy the value of the setting of the current extruder to all other extruders as well as the global container.
@pyqtSlot(str)
def copyValueToExtruders(self, key: str) -> None:
@@ -698,8 +626,8 @@ class MachineManager(QObject):
def copyAllValuesToExtruders(self) -> None:
if self._active_container_stack is None or self._global_container_stack is None:
return
- extruder_stacks = list(self._global_container_stack.extruders.values())
- for extruder_stack in extruder_stacks:
+
+ for extruder_stack in self._global_container_stack.extruderList:
if extruder_stack != self._active_container_stack:
for key in self._active_container_stack.userChanges.getAllKeys():
new_value = self._active_container_stack.getProperty(key, "value")
@@ -707,47 +635,14 @@ class MachineManager(QObject):
# Check if the value has to be replaced
extruder_stack.userChanges.setProperty(key, "value", new_value)
- @pyqtProperty(str, notify = activeVariantChanged)
- def activeVariantName(self) -> str:
- if self._active_container_stack:
- variant = self._active_container_stack.variant
- if variant:
- return variant.getName()
-
- return ""
-
- @pyqtProperty(str, notify = activeVariantChanged)
- def activeVariantId(self) -> str:
- if self._active_container_stack:
- variant = self._active_container_stack.variant
- if variant:
- return variant.getId()
-
- return ""
-
- @pyqtProperty(str, notify = activeVariantChanged)
- def activeVariantBuildplateName(self) -> str:
- if self._global_container_stack:
- variant = self._global_container_stack.variant
- if variant:
- return variant.getName()
-
- return ""
-
- @pyqtProperty(str, notify = globalContainerChanged)
- def activeDefinitionId(self) -> str:
- if self._global_container_stack:
- return self._global_container_stack.definition.id
-
- return ""
-
## Get the Definition ID to use to select quality profiles for the currently active machine
# \returns DefinitionID (string) if found, empty string otherwise
@pyqtProperty(str, notify = globalContainerChanged)
def activeQualityDefinitionId(self) -> str:
- if self._global_container_stack:
- return getMachineDefinitionIDForQualitySearch(self._global_container_stack.definition)
- return ""
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack:
+ return ""
+ return ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
## Gets how the active definition calls variants
# Caveat: per-definition-variant-title is currently not translated (though the fallback is)
@@ -770,6 +665,7 @@ class MachineManager(QObject):
@pyqtSlot(str)
def removeMachine(self, machine_id: str) -> None:
+ Logger.log("i", "Attempting to remove a machine with the id [%s]", machine_id)
# If the machine that is being removed is the currently active machine, set another machine as the active machine.
activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id)
@@ -781,7 +677,6 @@ class MachineManager(QObject):
self.setActiveMachine(other_machine_stacks[0]["id"])
metadata = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id)[0]
- network_key = metadata.get("um_network_key", None)
ExtruderManager.getInstance().removeMachineExtruders(machine_id)
containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id)
for container in containers:
@@ -789,31 +684,14 @@ class MachineManager(QObject):
CuraContainerRegistry.getInstance().removeContainer(machine_id)
# If the printer that is being removed is a network printer, the hidden printers have to be also removed
- if network_key:
- metadata_filter = {"um_network_key": network_key}
+ group_id = metadata.get("group_id", None)
+ if group_id:
+ metadata_filter = {"group_id": group_id}
hidden_containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
if hidden_containers:
# This reuses the method and remove all printers recursively
self.removeMachine(hidden_containers[0].getId())
- @pyqtProperty(bool, notify = globalContainerChanged)
- def hasMaterials(self) -> bool:
- if self._global_container_stack:
- return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False))
- return False
-
- @pyqtProperty(bool, notify = globalContainerChanged)
- def hasVariants(self) -> bool:
- if self._global_container_stack:
- return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variants", False))
- return False
-
- @pyqtProperty(bool, notify = globalContainerChanged)
- def hasVariantBuildplates(self) -> bool:
- if self._global_container_stack:
- return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variant_buildplates", False))
- return False
-
## The selected buildplate is compatible if it is compatible with all the materials in all the extruders
@pyqtProperty(bool, notify = activeMaterialChanged)
def variantBuildplateCompatible(self) -> bool:
@@ -821,15 +699,15 @@ class MachineManager(QObject):
return True
buildplate_compatible = True # It is compatible by default
- extruder_stacks = self._global_container_stack.extruders.values()
- for stack in extruder_stacks:
+ for stack in self._global_container_stack.extruderList:
if not stack.isEnabled:
continue
material_container = stack.material
if material_container == empty_material_container:
continue
if material_container.getMetaDataEntry("buildplate_compatible"):
- buildplate_compatible = buildplate_compatible and material_container.getMetaDataEntry("buildplate_compatible")[self.activeVariantBuildplateName]
+ active_buildplate_name = self.activeMachine.variant.name
+ buildplate_compatible = buildplate_compatible and material_container.getMetaDataEntry("buildplate_compatible")[active_buildplate_name]
return buildplate_compatible
@@ -845,8 +723,8 @@ class MachineManager(QObject):
# (material_left_compatible or material_left_usable) and
# (material_right_compatible or material_right_usable)
result = not self.variantBuildplateCompatible
- extruder_stacks = self._global_container_stack.extruders.values()
- for stack in extruder_stacks:
+
+ for stack in self._global_container_stack.extruderList:
material_container = stack.material
if material_container == empty_material_container:
continue
@@ -874,20 +752,15 @@ class MachineManager(QObject):
result = [] # type: List[str]
for setting_instance in container.findInstances():
setting_key = setting_instance.definition.key
- setting_enabled = self._global_container_stack.getProperty(setting_key, "enabled")
- if not setting_enabled:
- # A setting is not visible anymore
- result.append(setting_key)
- Logger.log("d", "Reset setting [%s] from [%s] because the setting is no longer enabled", setting_key, container)
- continue
-
if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"):
continue
old_value = container.getProperty(setting_key, "value")
+ if isinstance(old_value, SettingFunction):
+ old_value = old_value(self._global_container_stack)
if int(old_value) < 0:
continue
- if int(old_value) >= extruder_count or not self._global_container_stack.extruders[str(old_value)].isEnabled:
+ if int(old_value) >= extruder_count or not self._global_container_stack.extruderList[int(old_value)].isEnabled:
result.append(setting_key)
Logger.log("d", "Reset setting [%s] in [%s] because its old value [%s] is no longer valid", setting_key, container, old_value)
return result
@@ -903,9 +776,8 @@ class MachineManager(QObject):
# Apply quality changes that are incompatible to user changes, so we do not change the quality changes itself.
self._global_container_stack.userChanges.setProperty(setting_key, "value", self._default_extruder_position)
if add_user_changes:
- caution_message = Message(catalog.i18nc(
- "@info:generic",
- "Settings have been changed to match the current availability of extruders: [%s]" % ", ".join(add_user_changes)),
+ caution_message = Message(
+ catalog.i18nc("@info:message Followed by a list of settings.", "Settings have been changed to match the current availability of extruders:") + " [{settings_list}]".format(settings_list = ", ".join(add_user_changes)),
lifetime = 0,
title = catalog.i18nc("@info:title", "Settings updated"))
caution_message.show()
@@ -933,7 +805,7 @@ class MachineManager(QObject):
# Check to see if any objects are set to print with an extruder that will no longer exist
root_node = self._application.getController().getScene().getRoot()
- for node in DepthFirstIterator(root_node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(root_node):
if node.getMeshData():
extruder_nr = node.callDecoration("getActiveExtruderPosition")
@@ -958,7 +830,7 @@ class MachineManager(QObject):
if settable_per_extruder:
limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder"))
extruder_position = max(0, limit_to_extruder)
- extruder_stack = self.getExtruder(extruder_position)
+ extruder_stack = self._global_container_stack.extruderList[extruder_position]
if extruder_stack:
extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
else:
@@ -969,21 +841,15 @@ class MachineManager(QObject):
self._application.globalContainerStackChanged.emit()
self.forceUpdateAllSettings()
- @pyqtSlot(int, result = QObject)
- def getExtruder(self, position: int) -> Optional[ExtruderStack]:
- if self._global_container_stack:
- return self._global_container_stack.extruders.get(str(position))
- return None
-
def updateDefaultExtruder(self) -> None:
if self._global_container_stack is None:
return
- extruder_items = sorted(self._global_container_stack.extruders.items())
+
old_position = self._default_extruder_position
new_default_position = "0"
- for position, extruder in extruder_items:
+ for extruder in self._global_container_stack.extruderList:
if extruder.isEnabled:
- new_default_position = position
+ new_default_position = extruder.getMetaDataEntry("position", "0")
break
if new_default_position != old_position:
self._default_extruder_position = new_default_position
@@ -995,7 +861,7 @@ class MachineManager(QObject):
definition_changes_container = self._global_container_stack.definitionChanges
machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
extruder_count = 0
- for position, extruder in self._global_container_stack.extruders.items():
+ for position, extruder in enumerate(self._global_container_stack.extruderList):
if extruder.isEnabled and int(position) < machine_extruder_count:
extruder_count += 1
if self.numberExtrudersEnabled != extruder_count:
@@ -1006,7 +872,10 @@ class MachineManager(QObject):
def numberExtrudersEnabled(self) -> int:
if self._global_container_stack is None:
return 1
- return self._global_container_stack.definitionChanges.getProperty("extruders_enabled_count", "value")
+ extruders_enabled_count = self._global_container_stack.definitionChanges.getProperty("extruders_enabled_count", "value")
+ if extruders_enabled_count is None:
+ extruders_enabled_count = len(self._global_container_stack.extruderList)
+ return extruders_enabled_count
@pyqtProperty(str, notify = extruderChanged)
def defaultExtruderPosition(self) -> str:
@@ -1019,16 +888,16 @@ class MachineManager(QObject):
return
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
property_names = ["value", "resolve", "validationState"]
- for container in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
+ for container in [self._global_container_stack] + self._global_container_stack.extruderList:
for setting_key in container.getAllKeys():
container.propertiesChanged.emit(setting_key, property_names)
@pyqtSlot(int, bool)
def setExtruderEnabled(self, position: int, enabled: bool) -> None:
- extruder = self.getExtruder(position)
- if not extruder or self._global_container_stack is None:
+ if self._global_container_stack is None:
Logger.log("w", "Could not find extruder on position %s", position)
return
+ extruder = self._global_container_stack.extruderList[position]
extruder.setEnabled(enabled)
self.updateDefaultExtruder()
@@ -1050,28 +919,25 @@ class MachineManager(QObject):
self.forceUpdateAllSettings()
# Also trigger the build plate compatibility to update
self.activeMaterialChanged.emit()
-
- def _onMachineNameChanged(self) -> None:
- self.globalContainerChanged.emit()
+ self.activeIntentChanged.emit()
def _onMaterialNameChanged(self) -> None:
self.activeMaterialChanged.emit()
- def _onQualityNameChanged(self) -> None:
- self.activeQualityChanged.emit()
-
+ ## Get the signals that signal that the containers changed for all stacks.
+ #
+ # This includes the global stack and all extruder stacks. So if any
+ # container changed anywhere.
def _getContainerChangedSignals(self) -> List[Signal]:
if self._global_container_stack is None:
return []
- stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- stacks.append(self._global_container_stack)
- return [ s.containersChanged for s in stacks ]
+ return [s.containersChanged for s in ExtruderManager.getInstance().getActiveExtruderStacks() + [self._global_container_stack]]
@pyqtSlot(str, str, str)
def setSettingForAllExtruders(self, setting_name: str, property_name: str, property_value: str) -> None:
if self._global_container_stack is None:
return
- for key, extruder in self._global_container_stack.extruders.items():
+ for extruder in self._global_container_stack.extruderList:
container = extruder.userChanges
container.setProperty(setting_name, property_name, property_value)
@@ -1081,59 +947,46 @@ class MachineManager(QObject):
def resetSettingForAllExtruders(self, setting_name: str) -> None:
if self._global_container_stack is None:
return
- for key, extruder in self._global_container_stack.extruders.items():
+ for extruder in self._global_container_stack.extruderList:
container = extruder.userChanges
container.removeInstance(setting_name)
- @pyqtProperty("QVariantList", notify = globalContainerChanged)
- def currentExtruderPositions(self) -> List[str]:
- if self._global_container_stack is None:
- return []
- return sorted(list(self._global_container_stack.extruders.keys()))
-
## Update _current_root_material_id when the current root material was changed.
def _onRootMaterialChanged(self) -> None:
self._current_root_material_id = {}
+ changed = False
+
if self._global_container_stack:
- for position in self._global_container_stack.extruders:
- self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file")
+ for extruder in self._global_container_stack.extruderList:
+ material_id = extruder.material.getMetaDataEntry("base_file")
+ position = extruder.getMetaDataEntry("position")
+ if position not in self._current_root_material_id or material_id != self._current_root_material_id[position]:
+ changed = True
+ self._current_root_material_id[position] = material_id
+
+ if changed:
+ self.activeMaterialChanged.emit()
@pyqtProperty("QVariant", notify = rootMaterialChanged)
def currentRootMaterialId(self) -> Dict[str, str]:
return self._current_root_material_id
- ## Return the variant names in the extruder stack(s).
- ## For the variant in the global stack, use activeVariantBuildplateName
- @pyqtProperty("QVariant", notify = activeVariantChanged)
- def activeVariantNames(self) -> Dict[str, str]:
- result = {}
-
- active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- for stack in active_stacks:
- variant_container = stack.variant
- position = stack.getMetaDataEntry("position")
- if variant_container and variant_container != empty_variant_container:
- result[position] = variant_container.getName()
-
- return result
-
# Sets all quality and quality_changes containers to empty_quality and empty_quality_changes containers
# for all stacks in the currently active machine.
#
def _setEmptyQuality(self) -> None:
if self._global_container_stack is None:
return
- self._current_quality_group = None
- self._current_quality_changes_group = None
self._global_container_stack.quality = empty_quality_container
self._global_container_stack.qualityChanges = empty_quality_changes_container
- for extruder in self._global_container_stack.extruders.values():
+ for extruder in self._global_container_stack.extruderList:
extruder.quality = empty_quality_container
extruder.qualityChanges = empty_quality_changes_container
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
+ self._updateIntentWithQuality()
def _setQualityGroup(self, quality_group: Optional["QualityGroup"], empty_quality_changes: bool = True) -> None:
if self._global_container_stack is None:
@@ -1142,37 +995,33 @@ class MachineManager(QObject):
self._setEmptyQuality()
return
- if quality_group.node_for_global is None or quality_group.node_for_global.getContainer() is None:
+ if quality_group.node_for_global is None or quality_group.node_for_global.container is None:
return
for node in quality_group.nodes_for_extruders.values():
- if node.getContainer() is None:
+ if node.container is None:
return
- self._current_quality_group = quality_group
- if empty_quality_changes:
- self._current_quality_changes_group = None
-
# Set quality and quality_changes for the GlobalStack
- self._global_container_stack.quality = quality_group.node_for_global.getContainer()
+ self._global_container_stack.quality = quality_group.node_for_global.container
if empty_quality_changes:
self._global_container_stack.qualityChanges = empty_quality_changes_container
# Set quality and quality_changes for each ExtruderStack
for position, node in quality_group.nodes_for_extruders.items():
- self._global_container_stack.extruders[str(position)].quality = node.getContainer()
+ self._global_container_stack.extruders[str(position)].quality = node.container
if empty_quality_changes:
self._global_container_stack.extruders[str(position)].qualityChanges = empty_quality_changes_container
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
+ self._updateIntentWithQuality()
def _fixQualityChangesGroupToNotSupported(self, quality_changes_group: "QualityChangesGroup") -> None:
- nodes = [quality_changes_group.node_for_global] + list(quality_changes_group.nodes_for_extruders.values())
- containers = [n.getContainer() for n in nodes if n is not None]
- for container in containers:
- if container:
- container.setMetaDataEntry("quality_type", "not_supported")
+ metadatas = [quality_changes_group.metadata_for_global] + list(quality_changes_group.metadata_per_extruder.values())
+ for metadata in metadatas:
+ metadata["quality_type"] = "not_supported" # This actually changes the metadata of the container since they are stored by reference!
quality_changes_group.quality_type = "not_supported"
+ quality_changes_group.intent_category = "default"
def _setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None:
if self._global_container_stack is None:
@@ -1181,67 +1030,76 @@ class MachineManager(QObject):
# A custom quality can be created based on "not supported".
# In that case, do not set quality containers to empty.
quality_group = None
- if quality_type != "not_supported":
- quality_group_dict = self._quality_manager.getQualityGroups(self._global_container_stack)
- quality_group = quality_group_dict.get(quality_type)
+ if quality_type != "not_supported": # Find the quality group that the quality changes was based on.
+ quality_group = ContainerTree.getInstance().getCurrentQualityGroups().get(quality_type)
if quality_group is None:
self._fixQualityChangesGroupToNotSupported(quality_changes_group)
+ container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
quality_changes_container = empty_quality_changes_container
- quality_container = empty_quality_container # type: Optional[InstanceContainer]
- if quality_changes_group.node_for_global and quality_changes_group.node_for_global.getContainer():
- quality_changes_container = cast(InstanceContainer, quality_changes_group.node_for_global.getContainer())
- if quality_group is not None and quality_group.node_for_global and quality_group.node_for_global.getContainer():
- quality_container = quality_group.node_for_global.getContainer()
+ quality_container = empty_quality_container # type: InstanceContainer
+ if quality_changes_group.metadata_for_global:
+ global_containers = container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])
+ if global_containers:
+ quality_changes_container = global_containers[0]
+ if quality_changes_group.metadata_for_global:
+ containers = container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"])
+ if containers:
+ quality_changes_container = cast(InstanceContainer, containers[0])
+ if quality_group is not None and quality_group.node_for_global and quality_group.node_for_global.container:
+ quality_container = quality_group.node_for_global.container
self._global_container_stack.quality = quality_container
self._global_container_stack.qualityChanges = quality_changes_container
for position, extruder in self._global_container_stack.extruders.items():
- quality_changes_node = quality_changes_group.nodes_for_extruders.get(position)
quality_node = None
if quality_group is not None:
- quality_node = quality_group.nodes_for_extruders.get(position)
+ quality_node = quality_group.nodes_for_extruders.get(int(position))
quality_changes_container = empty_quality_changes_container
quality_container = empty_quality_container
- if quality_changes_node and quality_changes_node.getContainer():
- quality_changes_container = cast(InstanceContainer, quality_changes_node.getContainer())
- if quality_node and quality_node.getContainer():
- quality_container = quality_node.getContainer()
+ quality_changes_metadata = quality_changes_group.metadata_per_extruder.get(int(position))
+ if quality_changes_metadata:
+ containers = container_registry.findContainers(id = quality_changes_metadata["id"])
+ if containers:
+ quality_changes_container = cast(InstanceContainer, containers[0])
+ if quality_node and quality_node.container:
+ quality_container = quality_node.container
extruder.quality = quality_container
extruder.qualityChanges = quality_changes_container
- self._current_quality_group = quality_group
- self._current_quality_changes_group = quality_changes_group
+ self.setIntentByCategory(quality_changes_group.intent_category)
+
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
- def _setVariantNode(self, position: str, container_node: "ContainerNode") -> None:
- if container_node.getContainer() is None or self._global_container_stack is None:
+ def _setVariantNode(self, position: str, variant_node: "VariantNode") -> None:
+ if self._global_container_stack is None:
return
- self._global_container_stack.extruders[position].variant = container_node.getContainer()
+ self._global_container_stack.extruders[position].variant = variant_node.container
self.activeVariantChanged.emit()
def _setGlobalVariant(self, container_node: "ContainerNode") -> None:
if self._global_container_stack is None:
return
- self._global_container_stack.variant = container_node.getContainer()
+ self._global_container_stack.variant = container_node.container
if not self._global_container_stack.variant:
self._global_container_stack.variant = self._application.empty_variant_container
- def _setMaterial(self, position: str, container_node: Optional["ContainerNode"] = None) -> None:
+ def _setMaterial(self, position: str, material_node: Optional["MaterialNode"] = None) -> None:
if self._global_container_stack is None:
return
- if container_node and container_node.getContainer():
- self._global_container_stack.extruders[position].material = container_node.getContainer()
- root_material_id = container_node.getMetaDataEntry("base_file", None)
+ if material_node and material_node.container:
+ material_container = material_node.container
+ self._global_container_stack.extruders[position].material = material_container
+ root_material_id = material_container.getMetaDataEntry("base_file", None)
else:
- self._global_container_stack.extruders[position].material = empty_material_container
+ self._global_container_stack.extruderList[int(position)].material = empty_material_container
root_material_id = None
# The _current_root_material_id is used in the MaterialMenu to see which material is selected
- if root_material_id != self._current_root_material_id[position]:
+ if position not in self._current_root_material_id or root_material_id != self._current_root_material_id[position]:
self._current_root_material_id[position] = root_material_id
self.rootMaterialChanged.emit()
@@ -1249,22 +1107,21 @@ class MachineManager(QObject):
# Check material - variant compatibility
if self._global_container_stack is not None:
if Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)):
- for position, extruder in self._global_container_stack.extruders.items():
- if extruder.isEnabled and not extruder.material.getMetaDataEntry("compatible"):
- return False
+ for extruder in self._global_container_stack.extruderList:
+ if not extruder.isEnabled:
+ continue
if not extruder.material.getMetaDataEntry("compatible"):
return False
return True
## Update current quality type and machine after setting material
def _updateQualityWithMaterial(self, *args: Any) -> None:
- if self._global_container_stack is None:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
return
- Logger.log("i", "Updating quality/quality_changes due to material change")
- current_quality_type = None
- if self._current_quality_group:
- current_quality_type = self._current_quality_group.quality_type
- candidate_quality_groups = self._quality_manager.getQualityGroups(self._global_container_stack)
+ Logger.log("d", "Updating quality/quality_changes due to material change")
+ current_quality_type = global_stack.quality.getMetaDataEntry("quality_type")
+ candidate_quality_groups = ContainerTree.getInstance().getCurrentQualityGroups()
available_quality_types = {qt for qt, g in candidate_quality_groups.items() if g.is_available}
Logger.log("d", "Current quality type = [%s]", current_quality_type)
@@ -1275,7 +1132,7 @@ class MachineManager(QObject):
return
if not available_quality_types:
- if self._current_quality_changes_group is None:
+ if global_stack.qualityChanges == empty_quality_changes_container:
Logger.log("i", "No available quality types found, setting all qualities to empty (Not Supported).")
self._setEmptyQuality()
return
@@ -1288,6 +1145,9 @@ class MachineManager(QObject):
# The current quality type is not available so we use the preferred quality type if it's available,
# otherwise use one of the available quality types.
quality_type = sorted(list(available_quality_types))[0]
+ if self._global_container_stack is None:
+ Logger.log("e", "Global stack not present!")
+ return
preferred_quality_type = self._global_container_stack.getMetaDataEntry("preferred_quality_type")
if preferred_quality_type in available_quality_types:
quality_type = preferred_quality_type
@@ -1296,7 +1156,40 @@ class MachineManager(QObject):
current_quality_type, quality_type)
self._setQualityGroup(candidate_quality_groups[quality_type], empty_quality_changes = True)
- def updateMaterialWithVariant(self, position: Optional[str]) -> None:
+ ## Update the current intent after the quality changed
+ def _updateIntentWithQuality(self):
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return
+ Logger.log("d", "Updating intent due to quality change")
+
+ category = "default"
+
+ for extruder in global_stack.extruderList:
+ if not extruder.isEnabled:
+ continue
+ current_category = extruder.intent.getMetaDataEntry("intent_category", "default")
+ if current_category != "default" and current_category != category:
+ category = current_category
+ continue
+ # It's also possible that the qualityChanges has an opinion about the intent_category.
+ # This is in the case that a QC was made on an intent, but none of the materials have that intent.
+ # If the user switches back, we do want the intent to be selected again.
+ #
+ # Do not ask empty quality changes for intent category.
+ if extruder.qualityChanges.getId() == empty_quality_changes_container.getId():
+ continue
+ current_category = extruder.qualityChanges.getMetaDataEntry("intent_category", "default")
+ if current_category != "default" and current_category != category:
+ category = current_category
+ self.setIntentByCategory(category)
+
+ ## Update the material profile in the current stacks when the variant is
+ # changed.
+ # \param position The extruder stack to update. If provided with None, all
+ # extruder stacks will be updated.
+ @pyqtSlot()
+ def updateMaterialWithVariant(self, position: Optional[str] = None) -> None:
if self._global_container_stack is None:
return
if position is None:
@@ -1304,37 +1197,31 @@ class MachineManager(QObject):
else:
position_list = [position]
- buildplate_name = None
- if self._global_container_stack.variant.getId() != "empty_variant":
- buildplate_name = self._global_container_stack.variant.getName()
-
for position_item in position_list:
- extruder = self._global_container_stack.extruders[position_item]
+ try:
+ extruder = self._global_container_stack.extruderList[int(position_item)]
+ except IndexError:
+ continue
current_material_base_name = extruder.material.getMetaDataEntry("base_file")
- current_nozzle_name = None
- if extruder.variant.getId() != empty_variant_container.getId():
- current_nozzle_name = extruder.variant.getMetaDataEntry("name")
+ current_nozzle_name = extruder.variant.getMetaDataEntry("name")
- material_diameter = extruder.getCompatibleMaterialDiameter()
- candidate_materials = self._material_manager.getAvailableMaterials(
- self._global_container_stack.definition,
- current_nozzle_name,
- buildplate_name,
- material_diameter)
+ # If we can keep the current material after the switch, try to do so.
+ nozzle_node = ContainerTree.getInstance().machines[self._global_container_stack.definition.getId()].variants[current_nozzle_name]
+ candidate_materials = nozzle_node.materials
+ old_approximate_material_diameter = int(extruder.material.getMetaDataEntry("approximate_diameter", default = 3))
+ new_approximate_material_diameter = int(self._global_container_stack.extruderList[int(position_item)].getApproximateMaterialDiameter())
- if not candidate_materials:
- self._setMaterial(position_item, container_node = None)
- continue
-
- if current_material_base_name in candidate_materials:
+ # Only switch to the old candidate material if the approximate material diameter of the extruder stays the
+ # same.
+ if new_approximate_material_diameter == old_approximate_material_diameter and \
+ current_material_base_name in candidate_materials: # The current material is also available after the switch. Retain it.
new_material = candidate_materials[current_material_base_name]
self._setMaterial(position_item, new_material)
- continue
-
- # The current material is not available, find the preferred one
- material_node = self._material_manager.getDefaultMaterial(self._global_container_stack, position_item, current_nozzle_name)
- if material_node is not None:
+ else:
+ # The current material is not available, find the preferred one.
+ approximate_material_diameter = int(self._global_container_stack.extruderList[int(position_item)].getApproximateMaterialDiameter())
+ material_node = nozzle_node.preferredMaterial(approximate_material_diameter)
self._setMaterial(position_item, material_node)
## Given a printer definition name, select the right machine instance. In case it doesn't exist, create a new
@@ -1342,35 +1229,41 @@ class MachineManager(QObject):
@pyqtSlot(str)
def switchPrinterType(self, machine_name: str) -> None:
# Don't switch if the user tries to change to the same type of printer
- if self._global_container_stack is None or self.activeMachineDefinitionName == machine_name:
+ if self._global_container_stack is None or self._global_container_stack.definition.name == machine_name:
return
+ Logger.log("i", "Attempting to switch the printer type to [%s]", machine_name)
# Get the definition id corresponding to this machine name
machine_definition_id = CuraContainerRegistry.getInstance().findDefinitionContainers(name = machine_name)[0].getId()
# Try to find a machine with the same network key
- new_machine = self.getMachine(machine_definition_id, metadata_filter = {"um_network_key": self.activeMachineNetworkKey()})
+ metadata_filter = {"group_id": self._global_container_stack.getMetaDataEntry("group_id")}
+ new_machine = self.getMachine(machine_definition_id, metadata_filter = metadata_filter)
# If there is no machine, then create a new one and set it to the non-hidden instance
if not new_machine:
new_machine = CuraStackBuilder.createMachine(machine_definition_id + "_sync", machine_definition_id)
if not new_machine:
return
- new_machine.setMetaDataEntry("um_network_key", self.activeMachineNetworkKey())
- new_machine.setMetaDataEntry("group_name", self.activeMachineNetworkGroupName)
- new_machine.setMetaDataEntry("hidden", False)
- new_machine.setMetaDataEntry("connection_type", self._global_container_stack.getMetaDataEntry("connection_type"))
+
+ for metadata_key in self._global_container_stack.getMetaData():
+ if metadata_key in new_machine.getMetaData():
+ continue # Don't copy the already preset stuff.
+ new_machine.setMetaDataEntry(metadata_key, self._global_container_stack.getMetaDataEntry(metadata_key))
+ # Special case, group_id should be overwritten!
+ new_machine.setMetaDataEntry("group_id", self._global_container_stack.getMetaDataEntry("group_id"))
else:
Logger.log("i", "Found a %s with the key %s. Let's use it!", machine_name, self.activeMachineNetworkKey())
- new_machine.setMetaDataEntry("hidden", False)
# Set the current printer instance to hidden (the metadata entry must exist)
+ new_machine.setMetaDataEntry("hidden", False)
self._global_container_stack.setMetaDataEntry("hidden", True)
self.setActiveMachine(new_machine.getId())
@pyqtSlot(QObject)
- def applyRemoteConfiguration(self, configuration: ConfigurationModel) -> None:
+ def applyRemoteConfiguration(self, configuration: PrinterConfigurationModel) -> None:
if self._global_container_stack is None:
return
self.blurSettings.emit()
+ container_registry = CuraContainerRegistry.getInstance()
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
self.switchPrinterType(configuration.printerType)
@@ -1382,15 +1275,16 @@ class MachineManager(QObject):
need_to_show_message = False
for extruder_configuration in configuration.extruderConfigurations:
- extruder_has_hotend = extruder_configuration.hotendID != ""
- extruder_has_material = extruder_configuration.material.guid != ""
+ # We support "" or None, since the cloud uses None instead of empty strings
+ extruder_has_hotend = extruder_configuration.hotendID and extruder_configuration.hotendID != ""
+ extruder_has_material = extruder_configuration.material.guid and extruder_configuration.material.guid != ""
# If the machine doesn't have a hotend or material, disable this extruder
if not extruder_has_hotend or not extruder_has_material:
extruders_to_disable.add(extruder_configuration.position)
# If there's no material and/or nozzle on the printer, enable the first extruder and disable the rest.
- if len(extruders_to_disable) == len(self._global_container_stack.extruders):
+ if len(extruders_to_disable) == len(self._global_container_stack.extruderList):
extruders_to_disable.remove(min(extruders_to_disable))
for extruder_configuration in configuration.extruderConfigurations:
@@ -1398,41 +1292,33 @@ class MachineManager(QObject):
# If the machine doesn't have a hotend or material, disable this extruder
if int(position) in extruders_to_disable:
- self._global_container_stack.extruders[position].setEnabled(False)
+ self._global_container_stack.extruderList[int(position)].setEnabled(False)
need_to_show_message = True
disabled_used_extruder_position_set.add(int(position))
else:
- variant_container_node = self._variant_manager.getVariantNode(self._global_container_stack.definition.getId(),
- extruder_configuration.hotendID)
- material_container_node = self._material_manager.getMaterialNodeByType(self._global_container_stack,
- position,
- extruder_configuration.hotendID,
- configuration.buildplateConfiguration,
- extruder_configuration.material.guid)
- if variant_container_node:
- self._setVariantNode(position, variant_container_node)
- else:
- self._global_container_stack.extruders[position].variant = empty_variant_container
+ machine_node = ContainerTree.getInstance().machines.get(self._global_container_stack.definition.getId())
+ variant_node = machine_node.variants.get(extruder_configuration.hotendID)
+ if variant_node is None:
+ continue
+ self._setVariantNode(position, variant_node)
- if material_container_node:
- self._setMaterial(position, material_container_node)
- else:
- self._global_container_stack.extruders[position].material = empty_material_container
+ # Find the material profile that the printer has stored.
+ # This might find one of the duplicates if the user duplicated the material to sync with. But that's okay; both have this GUID so both are correct.
+ approximate_diameter = int(self._global_container_stack.extruderList[int(position)].getApproximateMaterialDiameter())
+ materials_with_guid = container_registry.findInstanceContainersMetadata(GUID = extruder_configuration.material.guid, approximate_diameter = str(approximate_diameter), ignore_case = True)
+ material_container_node = variant_node.preferredMaterial(approximate_diameter)
+ if materials_with_guid: # We also have the material profile that the printer wants to share.
+ base_file = materials_with_guid[0]["base_file"]
+ material_container_node = variant_node.materials.get(base_file, material_container_node)
+
+ self._setMaterial(position, material_container_node)
self._global_container_stack.extruders[position].setEnabled(True)
self.updateMaterialWithVariant(position)
+ self.updateDefaultExtruder()
self.updateNumberExtrudersEnabled()
-
- if configuration.buildplateConfiguration is not None:
- global_variant_container_node = self._variant_manager.getBuildplateVariantNode(self._global_container_stack.definition.getId(), configuration.buildplateConfiguration)
- if global_variant_container_node:
- self._setGlobalVariant(global_variant_container_node)
- else:
- self._global_container_stack.variant = empty_variant_container
- else:
- self._global_container_stack.variant = empty_variant_container
self._updateQualityWithMaterial()
if need_to_show_message:
@@ -1441,7 +1327,7 @@ class MachineManager(QObject):
# Show human-readable extruder names such as "Extruder Left", "Extruder Front" instead of "Extruder 1, 2, 3".
extruder_names = []
for extruder_position in sorted(disabled_used_extruder_position_set):
- extruder_stack = self._global_container_stack.extruders[str(extruder_position)]
+ extruder_stack = self._global_container_stack.extruderList[int(extruder_position)]
extruder_name = extruder_stack.definition.getName()
extruder_names.append(extruder_name)
extruders_str = ", ".join(extruder_names)
@@ -1454,31 +1340,6 @@ class MachineManager(QObject):
if self.hasUserSettings and self._application.getPreferences().getValue("cura/active_mode") == 1:
self._application.discardOrKeepProfileChanges()
- ## Find all container stacks that has the pair 'key = value' in its metadata and replaces the value with 'new_value'
- def replaceContainersMetadata(self, key: str, value: str, new_value: str) -> None:
- machines = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine")
- for machine in machines:
- if machine.getMetaDataEntry(key) == value:
- machine.setMetaDataEntry(key, new_value)
-
- ## This method checks if the name of the group stored in the definition container is correct.
- # After updating from 3.2 to 3.3 some group names may be temporary. If there is a mismatch in the name of the group
- # then all the container stacks are updated, both the current and the hidden ones.
- def checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
- if self._global_container_stack and device_id == self.activeMachineNetworkKey():
- # Check if the group_name is correct. If not, update all the containers connected to the same printer
- if self.activeMachineNetworkGroupName != group_name:
- metadata_filter = {"um_network_key": self.activeMachineNetworkKey()}
- containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
- for container in containers:
- container.setMetaDataEntry("group_name", group_name)
-
- ## This method checks if there is an instance connected to the given network_key
- def existNetworkInstances(self, network_key: str) -> bool:
- metadata_filter = {"um_network_key": network_key}
- containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
- return bool(containers)
-
@pyqtSlot("QVariant")
def setGlobalVariant(self, container_node: "ContainerNode") -> None:
self.blurSettings.emit()
@@ -1491,17 +1352,12 @@ class MachineManager(QObject):
def setMaterialById(self, position: str, root_material_id: str) -> None:
if self._global_container_stack is None:
return
- buildplate_name = None
- if self._global_container_stack.variant.getId() != "empty_variant":
- buildplate_name = self._global_container_stack.variant.getName()
machine_definition_id = self._global_container_stack.definition.id
position = str(position)
- extruder_stack = self._global_container_stack.extruders[position]
+ extruder_stack = self._global_container_stack.extruderList[int(position)]
nozzle_name = extruder_stack.variant.getName()
- material_diameter = extruder_stack.getApproximateMaterialDiameter()
- material_node = self._material_manager.getMaterialNode(machine_definition_id, nozzle_name, buildplate_name,
- material_diameter, root_material_id)
+ material_node = ContainerTree.getInstance().machines[machine_definition_id].variants[nozzle_name].materials[root_material_id]
self.setMaterial(position, material_node)
## Global_stack: if you want to provide your own global_stack instead of the current active one
@@ -1509,7 +1365,7 @@ class MachineManager(QObject):
@pyqtSlot(str, "QVariant")
def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None:
if global_stack is not None and global_stack != self._global_container_stack:
- global_stack.extruders[position].material = container_node.getContainer()
+ global_stack.extruders[position].material = container_node.container
return
position = str(position)
self.blurSettings.emit()
@@ -1526,15 +1382,16 @@ class MachineManager(QObject):
if self._global_container_stack is None:
return
machine_definition_id = self._global_container_stack.definition.id
- variant_node = self._variant_manager.getVariantNode(machine_definition_id, variant_name)
+ machine_node = ContainerTree.getInstance().machines.get(machine_definition_id)
+ variant_node = machine_node.variants.get(variant_name)
self.setVariant(position, variant_node)
@pyqtSlot(str, "QVariant")
- def setVariant(self, position: str, container_node: "ContainerNode") -> None:
+ def setVariant(self, position: str, variant_node: "VariantNode") -> None:
position = str(position)
self.blurSettings.emit()
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
- self._setVariantNode(position, container_node)
+ self._setVariantNode(position, variant_node)
self.updateMaterialWithVariant(position)
self._updateQualityWithMaterial()
@@ -1547,9 +1404,7 @@ class MachineManager(QObject):
if self._global_container_stack is None:
return
# Get all the quality groups for this global stack and filter out by quality_type
- quality_group_dict = self._quality_manager.getQualityGroups(self._global_container_stack)
- quality_group = quality_group_dict[quality_type]
- self.setQualityGroup(quality_group)
+ self.setQualityGroup(ContainerTree.getInstance().getCurrentQualityGroups()[quality_type])
## Optionally provide global_stack if you want to use your own
# The active global_stack is treated differently.
@@ -1563,11 +1418,11 @@ class MachineManager(QObject):
Logger.log("e", "Could not set quality group [%s] because it has no node_for_global", str(quality_group))
return
# This is not changing the quality for the active machine !!!!!!!!
- global_stack.quality = quality_group.node_for_global.getContainer()
- for extruder_nr, extruder_stack in global_stack.extruders.items():
+ global_stack.quality = quality_group.node_for_global.container
+ for extruder_nr, extruder_stack in enumerate(global_stack.extruderList):
quality_container = empty_quality_container
if extruder_nr in quality_group.nodes_for_extruders:
- container = quality_group.nodes_for_extruders[extruder_nr].getContainer()
+ container = quality_group.nodes_for_extruders[extruder_nr].container
quality_container = container if container is not None else quality_container
extruder_stack.quality = quality_container
return
@@ -1580,9 +1435,91 @@ class MachineManager(QObject):
if not no_dialog and self.hasUserSettings and self._application.getPreferences().getValue("cura/active_mode") == 1:
self._application.discardOrKeepProfileChanges()
- @pyqtProperty(QObject, fset = setQualityGroup, notify = activeQualityGroupChanged)
+ # The display name map of currently active quality.
+ # The display name has 2 parts, a main part and a suffix part.
+ # This display name is:
+ # - For built-in qualities (quality/intent): the quality type name, such as "Fine", "Normal", etc.
+ # - For custom qualities: - -
+ # Examples:
+ # - "my_profile - Fine" (only based on a default quality, no intent involved)
+ # - "my_profile - Engineering - Fine" (based on an intent)
+ @pyqtProperty("QVariantMap", notify = activeQualityDisplayNameChanged)
+ def activeQualityDisplayNameMap(self) -> Dict[str, str]:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return {"main": "",
+ "suffix": ""}
+
+ display_name = global_stack.quality.getName()
+
+ intent_category = self.activeIntentCategory
+ if intent_category != "default":
+ intent_display_name = IntentCategoryModel.translation(intent_category,
+ "name",
+ catalog.i18nc("@label", "Unknown"))
+ display_name = "{intent_name} - {the_rest}".format(intent_name = intent_display_name,
+ the_rest = display_name)
+
+ main_part = display_name
+ suffix_part = ""
+
+ # Not a custom quality
+ if global_stack.qualityChanges != empty_quality_changes_container:
+ main_part = self.activeQualityOrQualityChangesName
+ suffix_part = display_name
+
+ return {"main": main_part,
+ "suffix": suffix_part}
+
+ ## Change the intent category of the current printer.
+ #
+ # All extruders can change their profiles. If an intent profile is
+ # available with the desired intent category, that one will get chosen.
+ # Otherwise the intent profile will be left to the empty profile, which
+ # represents the "default" intent category.
+ # \param intent_category The intent category to change to.
+ @pyqtSlot(str)
+ def setIntentByCategory(self, intent_category: str) -> None:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return
+ container_tree = ContainerTree.getInstance()
+ for extruder in global_stack.extruderList:
+ definition_id = global_stack.definition.getId()
+ variant_name = extruder.variant.getName()
+ material_base_file = extruder.material.getMetaDataEntry("base_file")
+ quality_id = extruder.quality.getId()
+ if quality_id == empty_quality_container.getId():
+ extruder.intent = empty_intent_container
+ continue
+ quality_node = container_tree.machines[definition_id].variants[variant_name].materials[material_base_file].qualities[quality_id]
+
+ for intent_node in quality_node.intents.values():
+ if intent_node.intent_category == intent_category: # Found an intent with the correct category.
+ extruder.intent = intent_node.container
+ break
+ else: # No intent had the correct category.
+ extruder.intent = empty_intent_container
+
+ ## Get the currently activated quality group.
+ #
+ # If no printer is added yet or the printer doesn't have quality profiles,
+ # this returns ``None``.
+ # \return The currently active quality group.
def activeQualityGroup(self) -> Optional["QualityGroup"]:
- return self._current_quality_group
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_stack or global_stack.quality == empty_quality_container:
+ return None
+ return ContainerTree.getInstance().getCurrentQualityGroups().get(self.activeQualityType)
+
+ ## Get the name of the active quality group.
+ # \return The name of the active quality group.
+ @pyqtProperty(str, notify = activeQualityGroupChanged)
+ def activeQualityGroupName(self) -> str:
+ quality_group = self.activeQualityGroup()
+ if quality_group is None:
+ return ""
+ return quality_group.getName()
@pyqtSlot(QObject)
def setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", no_dialog: bool = False) -> None:
@@ -1599,30 +1536,50 @@ class MachineManager(QObject):
if self._global_container_stack is None:
return
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
- self._setQualityGroup(self._current_quality_group)
+ self._setQualityGroup(self.activeQualityGroup())
for stack in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
stack.userChanges.clear()
@pyqtProperty(QObject, fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged)
def activeQualityChangesGroup(self) -> Optional["QualityChangesGroup"]:
- return self._current_quality_changes_group
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None or global_stack.qualityChanges == empty_quality_changes_container:
+ return None
+
+ all_group_list = ContainerTree.getInstance().getCurrentQualityChangesGroups()
+ the_group = None
+ for group in all_group_list: # Match on the container ID of the global stack to find the quality changes group belonging to the active configuration.
+ if group.metadata_for_global and group.metadata_for_global["id"] == global_stack.qualityChanges.getId():
+ the_group = group
+ break
+
+ return the_group
@pyqtProperty(bool, notify = activeQualityChangesGroupChanged)
def hasCustomQuality(self) -> bool:
- return self._current_quality_changes_group is not None
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ return global_stack is None or global_stack.qualityChanges != empty_quality_changes_container
@pyqtProperty(str, notify = activeQualityGroupChanged)
def activeQualityOrQualityChangesName(self) -> str:
- name = empty_quality_container.getName()
- if self._current_quality_changes_group:
- name = self._current_quality_changes_group.name
- elif self._current_quality_group:
- name = self._current_quality_group.name
- return name
+ global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if not global_container_stack:
+ return empty_quality_container.getName()
+ if global_container_stack.qualityChanges != empty_quality_changes_container:
+ return global_container_stack.qualityChanges.getName()
+ return global_container_stack.quality.getName()
@pyqtProperty(bool, notify = activeQualityGroupChanged)
def hasNotSupportedQuality(self) -> bool:
- return self._current_quality_group is None and self._current_quality_changes_group is None
+ global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ return (not global_container_stack is None) and global_container_stack.quality == empty_quality_container and global_container_stack.qualityChanges == empty_quality_changes_container
+
+ @pyqtProperty(bool, notify = activeQualityGroupChanged)
+ def isActiveQualityCustom(self) -> bool:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return False
+ return global_stack.qualityChanges != empty_quality_changes_container
def _updateUponMaterialMetadataChange(self) -> None:
if self._global_container_stack is None:
diff --git a/cura/Settings/PerObjectContainerStack.py b/cura/Settings/PerObjectContainerStack.py
index 3589029517..a4f1f6ed06 100644
--- a/cura/Settings/PerObjectContainerStack.py
+++ b/cura/Settings/PerObjectContainerStack.py
@@ -12,6 +12,10 @@ from .CuraContainerStack import CuraContainerStack
class PerObjectContainerStack(CuraContainerStack):
+ def isDirty(self):
+ # This stack should never be auto saved, so always return that there is nothing to save.
+ return False
+
@override(CuraContainerStack)
def getProperty(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> Any:
if context is None:
@@ -34,7 +38,7 @@ class PerObjectContainerStack(CuraContainerStack):
if limit_to_extruder is not None:
limit_to_extruder = str(limit_to_extruder)
- # if this stack has the limit_to_extruder "not overriden", use the original limit_to_extruder as the current
+ # if this stack has the limit_to_extruder "not overridden", use the original limit_to_extruder as the current
# limit_to_extruder, so the values retrieved will be from the perspective of the original limit_to_extruder
# stack.
if limit_to_extruder == "-1":
@@ -42,7 +46,7 @@ class PerObjectContainerStack(CuraContainerStack):
limit_to_extruder = context.context["original_limit_to_extruder"]
if limit_to_extruder is not None and limit_to_extruder != "-1" and limit_to_extruder in global_stack.extruders:
- # set the original limit_to_extruder if this is the first stack that has a non-overriden limit_to_extruder
+ # set the original limit_to_extruder if this is the first stack that has a non-overridden limit_to_extruder
if "original_limit_to_extruder" not in context.context:
context.context["original_limit_to_extruder"] = limit_to_extruder
diff --git a/cura/Settings/SettingInheritanceManager.py b/cura/Settings/SettingInheritanceManager.py
index 12b541c3d8..7db579bf3f 100644
--- a/cura/Settings/SettingInheritanceManager.py
+++ b/cura/Settings/SettingInheritanceManager.py
@@ -28,20 +28,21 @@ if TYPE_CHECKING:
class SettingInheritanceManager(QObject):
def __init__(self, parent = None) -> None:
super().__init__(parent)
- Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
+
self._global_container_stack = None # type: Optional[ContainerStack]
self._settings_with_inheritance_warning = [] # type: List[str]
self._active_container_stack = None # type: Optional[ExtruderStack]
- self._onGlobalContainerChanged()
-
- ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
- self._onActiveExtruderChanged()
self._update_timer = QTimer()
self._update_timer.setInterval(500)
self._update_timer.setSingleShot(True)
self._update_timer.timeout.connect(self._update)
+ Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
+ ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
+ self._onGlobalContainerChanged()
+ self._onActiveExtruderChanged()
+
settingsWithIntheritanceChanged = pyqtSignal()
## Get the keys of all children settings with an override.
@@ -88,8 +89,8 @@ class SettingInheritanceManager(QObject):
self.settingsWithIntheritanceChanged.emit()
@pyqtSlot()
- def forceUpdate(self) -> None:
- self._update()
+ def scheduleUpdate(self) -> None:
+ self._update_timer.start()
def _onActiveExtruderChanged(self) -> None:
new_active_stack = ExtruderManager.getInstance().getActiveExtruderStack()
@@ -106,7 +107,7 @@ class SettingInheritanceManager(QObject):
if self._active_container_stack is not None:
self._active_container_stack.propertyChanged.connect(self._onPropertyChanged)
self._active_container_stack.containersChanged.connect(self._onContainersChanged)
- self._update() # Ensure that the settings_with_inheritance_warning list is populated.
+ self._update_timer.start() # Ensure that the settings_with_inheritance_warning list is populated.
def _onPropertyChanged(self, key: str, property_name: str) -> None:
if (property_name == "value" or property_name == "enabled") and self._global_container_stack:
diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py
index 429e6d16ec..2fa5234ec3 100644
--- a/cura/Settings/SettingOverrideDecorator.py
+++ b/cura/Settings/SettingOverrideDecorator.py
@@ -73,8 +73,8 @@ class SettingOverrideDecorator(SceneNodeDecorator):
# use value from the stack because there can be a delay in signal triggering and "_is_non_printing_mesh"
# has not been updated yet.
- deep_copy._is_non_printing_mesh = self.evaluateIsNonPrintingMesh()
- deep_copy._is_non_thumbnail_visible_mesh = self.evaluateIsNonThumbnailVisibleMesh()
+ deep_copy._is_non_printing_mesh = self._evaluateIsNonPrintingMesh()
+ deep_copy._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh()
return deep_copy
@@ -102,21 +102,21 @@ class SettingOverrideDecorator(SceneNodeDecorator):
def isNonPrintingMesh(self):
return self._is_non_printing_mesh
- def evaluateIsNonPrintingMesh(self):
+ def _evaluateIsNonPrintingMesh(self):
return any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_printing_mesh_settings)
def isNonThumbnailVisibleMesh(self):
return self._is_non_thumbnail_visible_mesh
- def evaluateIsNonThumbnailVisibleMesh(self):
+ def _evaluateIsNonThumbnailVisibleMesh(self):
return any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_thumbnail_visible_settings)
- def _onSettingChanged(self, instance, property_name): # Reminder: 'property' is a built-in function
+ def _onSettingChanged(self, setting_key, property_name): # Reminder: 'property' is a built-in function
+ # We're only interested in a few settings and only if it's value changed.
if property_name == "value":
# Trigger slice/need slicing if the value has changed.
- self._is_non_printing_mesh = self.evaluateIsNonPrintingMesh()
- self._is_non_thumbnail_visible_mesh = self.evaluateIsNonThumbnailVisibleMesh()
-
+ self._is_non_printing_mesh = self._evaluateIsNonPrintingMesh()
+ self._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh()
Application.getInstance().getBackend().needsSlicing()
Application.getInstance().getBackend().tickle()
diff --git a/cura/Settings/SimpleModeSettingsManager.py b/cura/Settings/SimpleModeSettingsManager.py
index b1896a9205..3923435e63 100644
--- a/cura/Settings/SimpleModeSettingsManager.py
+++ b/cura/Settings/SimpleModeSettingsManager.py
@@ -39,8 +39,8 @@ class SimpleModeSettingsManager(QObject):
user_setting_keys.update(global_stack.userChanges.getAllKeys())
# check user settings in the extruder stacks
- if global_stack.extruders:
- for extruder_stack in global_stack.extruders.values():
+ if global_stack.extruderList:
+ for extruder_stack in global_stack.extruderList:
user_setting_keys.update(extruder_stack.userChanges.getAllKeys())
# remove settings that are visible in recommended (we don't show the reset button for those)
diff --git a/cura/Settings/cura_empty_instance_containers.py b/cura/Settings/cura_empty_instance_containers.py
index d76407ed79..b142c53c11 100644
--- a/cura/Settings/cura_empty_instance_containers.py
+++ b/cura/Settings/cura_empty_instance_containers.py
@@ -1,9 +1,11 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import copy
from UM.Settings.constant_instance_containers import EMPTY_CONTAINER_ID, empty_container
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
# Empty definition changes
@@ -23,12 +25,15 @@ EMPTY_MATERIAL_CONTAINER_ID = "empty_material"
empty_material_container = copy.deepcopy(empty_container)
empty_material_container.setMetaDataEntry("id", EMPTY_MATERIAL_CONTAINER_ID)
empty_material_container.setMetaDataEntry("type", "material")
+empty_material_container.setMetaDataEntry("base_file", "empty_material")
+empty_material_container.setMetaDataEntry("GUID", "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")
+empty_material_container.setMetaDataEntry("material", "empty")
# Empty quality
EMPTY_QUALITY_CONTAINER_ID = "empty_quality"
empty_quality_container = copy.deepcopy(empty_container)
empty_quality_container.setMetaDataEntry("id", EMPTY_QUALITY_CONTAINER_ID)
-empty_quality_container.setName("Not Supported")
+empty_quality_container.setName(catalog.i18nc("@info:not supported profile", "Not supported"))
empty_quality_container.setMetaDataEntry("quality_type", "not_supported")
empty_quality_container.setMetaDataEntry("type", "quality")
empty_quality_container.setMetaDataEntry("supported", False)
@@ -39,6 +44,32 @@ empty_quality_changes_container = copy.deepcopy(empty_container)
empty_quality_changes_container.setMetaDataEntry("id", EMPTY_QUALITY_CHANGES_CONTAINER_ID)
empty_quality_changes_container.setMetaDataEntry("type", "quality_changes")
empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported")
+empty_quality_changes_container.setMetaDataEntry("intent_category", "not_supported")
+
+# Empty intent
+EMPTY_INTENT_CONTAINER_ID = "empty_intent"
+empty_intent_container = copy.deepcopy(empty_container)
+empty_intent_container.setMetaDataEntry("id", EMPTY_INTENT_CONTAINER_ID)
+empty_intent_container.setMetaDataEntry("type", "intent")
+empty_intent_container.setMetaDataEntry("intent_category", "default")
+empty_intent_container.setName(catalog.i18nc("@info:No intent profile selected", "Default"))
+
+
+# All empty container IDs set
+ALL_EMPTY_CONTAINER_ID_SET = {
+ EMPTY_CONTAINER_ID,
+ EMPTY_DEFINITION_CHANGES_CONTAINER_ID,
+ EMPTY_VARIANT_CONTAINER_ID,
+ EMPTY_MATERIAL_CONTAINER_ID,
+ EMPTY_QUALITY_CONTAINER_ID,
+ EMPTY_QUALITY_CHANGES_CONTAINER_ID,
+ EMPTY_INTENT_CONTAINER_ID
+}
+
+
+# Convenience function to check if a container ID represents an empty container.
+def isEmptyContainer(container_id: str) -> bool:
+ return container_id in ALL_EMPTY_CONTAINER_ID_SET
__all__ = ["EMPTY_CONTAINER_ID",
@@ -52,5 +83,9 @@ __all__ = ["EMPTY_CONTAINER_ID",
"EMPTY_QUALITY_CHANGES_CONTAINER_ID",
"empty_quality_changes_container",
"EMPTY_QUALITY_CONTAINER_ID",
- "empty_quality_container"
+ "empty_quality_container",
+ "ALL_EMPTY_CONTAINER_ID_SET",
+ "isEmptyContainer",
+ "EMPTY_INTENT_CONTAINER_ID",
+ "empty_intent_container"
]
diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py
index cf07b143c6..6fcf0da6cf 100644
--- a/cura/SingleInstance.py
+++ b/cura/SingleInstance.py
@@ -87,7 +87,7 @@ class SingleInstance:
if command == "clear-all":
self._application.callLater(lambda: self._application.deleteAll())
- # Command: Load a model file
+ # Command: Load a model or project file
elif command == "open":
self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f))
diff --git a/cura/Snapshot.py b/cura/Snapshot.py
index b730c1fdcf..353b5ae17c 100644
--- a/cura/Snapshot.py
+++ b/cura/Snapshot.py
@@ -48,12 +48,12 @@ class Snapshot:
# determine zoom and look at
bbox = None
for node in DepthFirstIterator(root):
- 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()
-
+ 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()
# If there is no bounding box, it means that there is no model in the buildplate
if bbox is None:
return None
@@ -66,7 +66,7 @@ class Snapshot:
looking_from_offset = Vector(-1, 1, 2)
if size > 0:
# determine the watch distance depending on the size
- looking_from_offset = looking_from_offset * size * 1.3
+ looking_from_offset = looking_from_offset * size * 1.75
camera.setPosition(look_at + looking_from_offset)
camera.lookAt(look_at)
@@ -85,8 +85,10 @@ class Snapshot:
preview_pass.setCamera(camera)
preview_pass.render()
pixel_output = preview_pass.getOutput()
-
- min_x, max_x, min_y, max_y = Snapshot.getImageBoundaries(pixel_output)
+ try:
+ min_x, max_x, min_y, max_y = Snapshot.getImageBoundaries(pixel_output)
+ except ValueError:
+ return None
size = max((max_x - min_x) / render_width, (max_y - min_y) / render_height)
if size > 0.5 or satisfied:
diff --git a/cura/Stages/CuraStage.py b/cura/Stages/CuraStage.py
index 844b0d0768..6c4d46dd72 100644
--- a/cura/Stages/CuraStage.py
+++ b/cura/Stages/CuraStage.py
@@ -1,29 +1,32 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import pyqtProperty, QUrl
-
-from UM.Stage import Stage
-
-
-# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
-# to indicate this.
-# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
-# buttons and elements. This component will be drawn over the bar & main component.
-# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
-# of the screen.
-class CuraStage(Stage):
- def __init__(self, parent = None) -> None:
- super().__init__(parent)
-
- @pyqtProperty(str, constant = True)
- def stageId(self) -> str:
- return self.getPluginId()
-
- @pyqtProperty(QUrl, constant = True)
- def mainComponent(self) -> QUrl:
- return self.getDisplayComponent("main")
-
- @pyqtProperty(QUrl, constant = True)
- def stageMenuComponent(self) -> QUrl:
- return self.getDisplayComponent("menu")
\ No newline at end of file
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import pyqtProperty, QUrl
+
+from UM.Stage import Stage
+
+
+# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
+# to indicate this.
+# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
+# buttons and elements. This component will be drawn over the bar & main component.
+# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
+# of the screen.
+class CuraStage(Stage):
+ def __init__(self, parent = None) -> None:
+ super().__init__(parent)
+
+ @pyqtProperty(str, constant = True)
+ def stageId(self) -> str:
+ return self.getPluginId()
+
+ @pyqtProperty(QUrl, constant = True)
+ def mainComponent(self) -> QUrl:
+ return self.getDisplayComponent("main")
+
+ @pyqtProperty(QUrl, constant = True)
+ def stageMenuComponent(self) -> QUrl:
+ return self.getDisplayComponent("menu")
+
+
+__all__ = ["CuraStage"]
diff --git a/cura/Stages/__init__.py b/cura/Stages/__init__.py
index 2977645166..e69de29bb2 100644
--- a/cura/Stages/__init__.py
+++ b/cura/Stages/__init__.py
@@ -1,2 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/cura/UI/AddPrinterPagesModel.py b/cura/UI/AddPrinterPagesModel.py
new file mode 100644
index 0000000000..d40da59b2a
--- /dev/null
+++ b/cura/UI/AddPrinterPagesModel.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from .WelcomePagesModel import WelcomePagesModel
+
+
+#
+# This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for adding a printer,
+# so only the steps for adding a printer is included.
+#
+class AddPrinterPagesModel(WelcomePagesModel):
+
+ def initialize(self) -> None:
+ self._pages.append({"id": "add_network_or_local_printer",
+ "page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"),
+ "next_page_id": "machine_actions",
+ "next_page_button_text": self._catalog.i18nc("@action:button", "Add"),
+ "previous_page_button_text": self._catalog.i18nc("@action:button", "Cancel"),
+ })
+ self._pages.append({"id": "add_printer_by_ip",
+ "page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"),
+ "next_page_id": "machine_actions",
+ })
+ self._pages.append({"id": "machine_actions",
+ "page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
+ "should_show_function": self.shouldShowMachineActions,
+ })
+ self.setItems(self._pages)
+
+
+__all__ = ["AddPrinterPagesModel"]
diff --git a/cura/CuraSplashScreen.py b/cura/UI/CuraSplashScreen.py
similarity index 94%
rename from cura/CuraSplashScreen.py
rename to cura/UI/CuraSplashScreen.py
index 77c9ad1427..05231c106d 100644
--- a/cura/CuraSplashScreen.py
+++ b/cura/UI/CuraSplashScreen.py
@@ -56,11 +56,11 @@ class CuraSplashScreen(QSplashScreen):
if buildtype:
version[0] += " (%s)" % buildtype
- # draw version text
+ # Draw version text
font = QFont() # Using system-default font here
font.setPixelSize(37)
painter.setFont(font)
- painter.drawText(215, 66, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[0])
+ painter.drawText(60, 66, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[0])
if len(version) > 1:
font.setPixelSize(16)
painter.setFont(font)
@@ -68,14 +68,14 @@ class CuraSplashScreen(QSplashScreen):
painter.drawText(247, 105, 330 * self._scale, 255 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[1])
painter.setPen(QColor(255, 255, 255, 255))
- # draw the loading image
+ # Draw the loading image
pen = QPen()
pen.setWidth(6 * self._scale)
pen.setColor(QColor(32, 166, 219, 255))
painter.setPen(pen)
painter.drawArc(60, 150, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16)
- # draw message text
+ # Draw message text
if self._current_message:
font = QFont() # Using system-default font here
font.setPixelSize(13)
diff --git a/cura/MachineActionManager.py b/cura/UI/MachineActionManager.py
similarity index 98%
rename from cura/MachineActionManager.py
rename to cura/UI/MachineActionManager.py
index db0f7bfbff..aa90e909e2 100644
--- a/cura/MachineActionManager.py
+++ b/cura/UI/MachineActionManager.py
@@ -12,7 +12,7 @@ from UM.PluginRegistry import PluginRegistry # So MachineAction can be added as
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
from cura.Settings.GlobalStack import GlobalStack
- from .MachineAction import MachineAction
+ from cura.MachineAction import MachineAction
## Raised when trying to add an unknown machine action as a required action
@@ -136,7 +136,7 @@ class MachineActionManager(QObject):
# action multiple times).
# \param definition_id The ID of the definition that you want to get the "on added" actions for.
# \returns List of actions.
- @pyqtSlot(str, result="QVariantList")
+ @pyqtSlot(str, result = "QVariantList")
def getFirstStartActions(self, definition_id: str) -> List["MachineAction"]:
if definition_id in self._first_start_actions:
return self._first_start_actions[definition_id]
diff --git a/cura/UI/MachineSettingsManager.py b/cura/UI/MachineSettingsManager.py
new file mode 100644
index 0000000000..671bb0ece0
--- /dev/null
+++ b/cura/UI/MachineSettingsManager.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional, TYPE_CHECKING
+from PyQt5.QtCore import QObject, pyqtSlot
+
+from UM.i18n import i18nCatalog
+
+from cura.Machines.ContainerTree import ContainerTree
+
+if TYPE_CHECKING:
+ from cura.CuraApplication import CuraApplication
+
+
+#
+# This manager provides (convenience) functions to the Machine Settings Dialog QML to update certain machine settings.
+#
+class MachineSettingsManager(QObject):
+
+ def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+ self._i18n_catalog = i18nCatalog("cura")
+
+ self._application = application
+
+ # Force rebuilding the build volume by reloading the global container stack. This is a bit of a hack, but it seems
+ # quite enough.
+ @pyqtSlot()
+ def forceUpdate(self) -> None:
+ self._application.getMachineManager().globalContainerChanged.emit()
+
+ # Function for the Machine Settings panel (QML) to update the compatible material diameter after a user has changed
+ # an extruder's compatible material diameter. This ensures that after the modification, changes can be notified
+ # and updated right away.
+ @pyqtSlot(int)
+ def updateMaterialForDiameter(self, extruder_position: int) -> None:
+ # Updates the material container to a material that matches the material diameter set for the printer
+ self._application.getMachineManager().updateMaterialWithVariant(str(extruder_position))
+
+ @pyqtSlot(int)
+ def setMachineExtruderCount(self, extruder_count: int) -> None:
+ # Note: this method was in this class before, but since it's quite generic and other plugins also need it
+ # it was moved to the machine manager instead. Now this method just calls the machine manager.
+ self._application.getMachineManager().setActiveMachineExtruderCount(extruder_count)
+
+ # Function for the Machine Settings panel (QML) to update after the user changes "Number of Extruders".
+ #
+ # fieldOfView: The Ultimaker 2 family (not 2+) does not have materials in Cura by default, because the material is
+ # to be set on the printer. But when switching to Marlin flavor, the printer firmware can not change/insert material
+ # settings on the fly so they need to be configured in Cura. So when switching between gcode flavors, materials may
+ # need to be enabled/disabled.
+ @pyqtSlot()
+ def updateHasMaterialsMetadata(self):
+ machine_manager = self._application.getMachineManager()
+ global_stack = machine_manager.activeMachine
+
+ definition = global_stack.definition
+ if definition.getProperty("machine_gcode_flavor", "value") != "UltiGCode" or definition.getMetaDataEntry(
+ "has_materials", False):
+ # In other words: only continue for the UM2 (extended), but not for the UM2+
+ return
+
+ extruder_positions = list(global_stack.extruders.keys())
+ has_materials = global_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
+
+ material_node = None
+ if has_materials:
+ global_stack.setMetaDataEntry("has_materials", True)
+ else:
+ # The metadata entry is stored in an ini, and ini files are parsed as strings only.
+ # Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
+ if "has_materials" in global_stack.getMetaData():
+ global_stack.removeMetaDataEntry("has_materials")
+
+ # set materials
+ for position in extruder_positions:
+ if has_materials:
+ extruder = global_stack.extruderList[int(position)]
+ approximate_diameter = extruder.getApproximateMaterialDiameter()
+ variant_node = ContainerTree.getInstance().machines[global_stack.definition.getId()].variants[extruder.variant.getName()]
+ material_node = variant_node.preferredMaterial(approximate_diameter)
+ machine_manager.setMaterial(position, material_node)
+
+ self.forceUpdate()
diff --git a/cura/UI/ObjectsModel.py b/cura/UI/ObjectsModel.py
new file mode 100644
index 0000000000..5526b41098
--- /dev/null
+++ b/cura/UI/ObjectsModel.py
@@ -0,0 +1,184 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from UM.Logger import Logger
+import re
+from typing import Any, Dict, List, Optional, Union
+
+from PyQt5.QtCore import QTimer, Qt
+
+from UM.Application import Application
+from UM.Qt.ListModel import ListModel
+from UM.Scene.Camera import Camera
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+from UM.Scene.SceneNode import SceneNode
+from UM.Scene.Selection import Selection
+from UM.i18n import i18nCatalog
+
+catalog = i18nCatalog("cura")
+
+
+# Simple convenience class to keep stuff together. Since we're still stuck on python 3.5, we can't use the full
+# typed named tuple, so we have to do it like this.
+# Once we are at python 3.6, feel free to change this to a named tuple.
+class _NodeInfo:
+ def __init__(self, index_to_node: Optional[Dict[int, SceneNode]] = None, nodes_to_rename: Optional[List[SceneNode]] = None, is_group: bool = False) -> None:
+ if index_to_node is None:
+ index_to_node = {}
+ if nodes_to_rename is None:
+ nodes_to_rename = []
+ self.index_to_node = index_to_node # type: Dict[int, SceneNode]
+ self.nodes_to_rename = nodes_to_rename # type: List[SceneNode]
+ self.is_group = is_group # type: bool
+
+
+## Keep track of all objects in the project
+class ObjectsModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ SelectedRole = Qt.UserRole + 2
+ OutsideAreaRole = Qt.UserRole + 3
+ BuilplateNumberRole = Qt.UserRole + 4
+ NodeRole = Qt.UserRole + 5
+
+ def __init__(self, parent = None) -> None:
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.SelectedRole, "selected")
+ self.addRoleName(self.OutsideAreaRole, "outside_build_area")
+ self.addRoleName(self.BuilplateNumberRole, "buildplate_number")
+ self.addRoleName(self.NodeRole, "node")
+
+ Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSceneDelayed)
+ Application.getInstance().getPreferences().preferenceChanged.connect(self._updateDelayed)
+ Selection.selectionChanged.connect(self._updateDelayed)
+
+ self._update_timer = QTimer()
+ self._update_timer.setInterval(200)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._update)
+
+ self._build_plate_number = -1
+
+ self._group_name_template = catalog.i18nc("@label", "Group #{group_nr}")
+ self._group_name_prefix = self._group_name_template.split("#")[0]
+
+ self._naming_regex = re.compile("^(.+)\(([0-9]+)\)$")
+
+ def setActiveBuildPlate(self, nr: int) -> None:
+ if self._build_plate_number != nr:
+ self._build_plate_number = nr
+ self._update()
+
+ def _updateSceneDelayed(self, source) -> None:
+ if not isinstance(source, Camera):
+ self._update_timer.start()
+
+ def _updateDelayed(self, *args) -> None:
+ self._update_timer.start()
+
+ def _shouldNodeBeHandled(self, node: SceneNode) -> bool:
+ is_group = bool(node.callDecoration("isGroup"))
+ if not node.callDecoration("isSliceable") and not is_group:
+ return False
+
+ parent = node.getParent()
+ if parent and parent.callDecoration("isGroup"):
+ return False # Grouped nodes don't need resetting as their parent (the group) is resetted)
+
+ node_build_plate_number = node.callDecoration("getBuildPlateNumber")
+ if Application.getInstance().getPreferences().getValue("view/filter_current_build_plate") and node_build_plate_number != self._build_plate_number:
+ return False
+
+ return True
+
+ def _renameNodes(self, node_info_dict: Dict[str, _NodeInfo]) -> List[SceneNode]:
+ # Go through all names and find out the names for all nodes that need to be renamed.
+ all_nodes = [] # type: List[SceneNode]
+ for name, node_info in node_info_dict.items():
+ # First add the ones that do not need to be renamed.
+ for node in node_info.index_to_node.values():
+ all_nodes.append(node)
+
+ # Generate new names for the nodes that need to be renamed
+ current_index = 0
+ for node in node_info.nodes_to_rename:
+ current_index += 1
+ while current_index in node_info.index_to_node:
+ current_index += 1
+
+ if not node_info.is_group:
+ new_group_name = "{0}({1})".format(name, current_index)
+ else:
+ new_group_name = "{0}#{1}".format(name, current_index)
+
+ old_name = node.getName()
+ node.setName(new_group_name)
+ Logger.log("d", "Node [%s] renamed to [%s]", old_name, new_group_name)
+ all_nodes.append(node)
+ return all_nodes
+
+ def _update(self, *args) -> None:
+ nodes = [] # type: List[Dict[str, Union[str, int, bool, SceneNode]]]
+ name_to_node_info_dict = {} # type: Dict[str, _NodeInfo]
+ for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()): # type: ignore
+ if not self._shouldNodeBeHandled(node):
+ continue
+
+ is_group = bool(node.callDecoration("isGroup"))
+
+ force_rename = False
+ if not is_group:
+ # Handle names for individual nodes
+ name = node.getName()
+
+ name_match = self._naming_regex.fullmatch(name)
+ if name_match is None:
+ original_name = name
+ name_index = 0
+ else:
+ original_name = name_match.groups()[0]
+ name_index = int(name_match.groups()[1])
+ else:
+ # Handle names for grouped nodes
+ original_name = self._group_name_prefix
+
+ current_name = node.getName()
+ if current_name.startswith(self._group_name_prefix):
+ name_index = int(current_name.split("#")[-1])
+ else:
+ # Force rename this group because this node has not been named as a group yet, probably because
+ # it's a newly created group.
+ name_index = 0
+ force_rename = True
+
+ if original_name not in name_to_node_info_dict:
+ # Keep track of 2 things:
+ # - known indices for nodes which doesn't need to be renamed
+ # - a list of nodes that need to be renamed. When renaming then, we should avoid using the known indices.
+ name_to_node_info_dict[original_name] = _NodeInfo(is_group = is_group)
+ node_info = name_to_node_info_dict[original_name]
+ if not force_rename and name_index not in node_info.index_to_node:
+ node_info.index_to_node[name_index] = node
+ else:
+ node_info.nodes_to_rename.append(node)
+
+ all_nodes = self._renameNodes(name_to_node_info_dict)
+
+ for node in all_nodes:
+ if hasattr(node, "isOutsideBuildArea"):
+ is_outside_build_area = node.isOutsideBuildArea() # type: ignore
+ else:
+ is_outside_build_area = False
+
+ node_build_plate_number = node.callDecoration("getBuildPlateNumber")
+
+ nodes.append({
+ "name": node.getName(),
+ "selected": Selection.isSelected(node),
+ "outside_build_area": is_outside_build_area,
+ "buildplate_number": node_build_plate_number,
+ "node": node
+ })
+
+ nodes = sorted(nodes, key=lambda n: n["name"])
+ self.setItems(nodes)
diff --git a/cura/PrintInformation.py b/cura/UI/PrintInformation.py
similarity index 98%
rename from cura/PrintInformation.py
rename to cura/UI/PrintInformation.py
index ba7c74fd6d..abf1083836 100644
--- a/cura/PrintInformation.py
+++ b/cura/UI/PrintInformation.py
@@ -5,8 +5,7 @@ import json
import math
import os
import unicodedata
-import re # To create abbreviations for printer names.
-from typing import Dict, List, Optional
+from typing import Dict, List, Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
@@ -16,8 +15,6 @@ from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
-from typing import TYPE_CHECKING
-
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
@@ -84,6 +81,7 @@ class PrintInformation(QObject):
"support_interface": catalog.i18nc("@tooltip", "Support Interface"),
"support": catalog.i18nc("@tooltip", "Support"),
"skirt": catalog.i18nc("@tooltip", "Skirt"),
+ "prime_tower": catalog.i18nc("@tooltip", "Prime Tower"),
"travel": catalog.i18nc("@tooltip", "Travel"),
"retract": catalog.i18nc("@tooltip", "Retractions"),
"none": catalog.i18nc("@tooltip", "Other")
@@ -199,11 +197,7 @@ class PrintInformation(QObject):
material_preference_values = json.loads(self._application.getInstance().getPreferences().getValue("cura/material_settings"))
- extruder_stacks = global_stack.extruders
-
- for position in extruder_stacks:
- extruder_stack = extruder_stacks[position]
- index = int(position)
+ for index, extruder_stack in enumerate(global_stack.extruderList):
if index >= len(self._material_amounts):
continue
amount = self._material_amounts[index]
diff --git a/cura/UI/RecommendedMode.py b/cura/UI/RecommendedMode.py
new file mode 100644
index 0000000000..47b617740a
--- /dev/null
+++ b/cura/UI/RecommendedMode.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import QObject, pyqtSlot
+
+from cura import CuraApplication
+
+#
+# This object contains helper/convenience functions for Recommended mode.
+#
+class RecommendedMode(QObject):
+
+ # Sets to use the adhesion or not for the "Adhesion" CheckBox in Recommended mode.
+ @pyqtSlot(bool)
+ def setAdhesion(self, checked: bool) -> None:
+ application = CuraApplication.CuraApplication.getInstance()
+ global_stack = application.getMachineManager().activeMachine
+ if global_stack is None:
+ return
+
+ # Remove the adhesion type value set by the user.
+ adhesion_type_key = "adhesion_type"
+ user_changes_container = global_stack.userChanges
+ if adhesion_type_key in user_changes_container.getAllKeys():
+ user_changes_container.removeInstance(adhesion_type_key)
+
+ # Get the default value of adhesion type after user's value has been removed.
+ # skirt and none are counted as "no adhesion", the others are considered as "with adhesion". The conditions are
+ # as the following:
+ # - if the user checks the adhesion checkbox, get the default value (including the custom quality) for adhesion
+ # type.
+ # (1) If the default value is "skirt" or "none" (no adhesion), set adhesion_type to "brim".
+ # (2) If the default value is "with adhesion", do nothing.
+ # - if the user unchecks the adhesion checkbox, get the default value (including the custom quality) for
+ # adhesion type.
+ # (1) If the default value is "skirt" or "none" (no adhesion), do nothing.
+ # (2) Otherwise, set adhesion_type to "skirt".
+ value = global_stack.getProperty(adhesion_type_key, "value")
+ if checked:
+ if value in ("skirt", "none"):
+ value = "brim"
+ else:
+ if value not in ("skirt", "none"):
+ value = "skirt"
+
+ user_changes_container.setProperty(adhesion_type_key, "value", value)
+
+
+__all__ = ["RecommendedMode"]
diff --git a/cura/UI/TextManager.py b/cura/UI/TextManager.py
new file mode 100644
index 0000000000..86838a0b48
--- /dev/null
+++ b/cura/UI/TextManager.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import collections
+from typing import Optional, Dict, List, cast
+
+from PyQt5.QtCore import QObject, pyqtSlot
+
+from UM.Resources import Resources
+from UM.Version import Version
+
+
+#
+# This manager provides means to load texts to QML.
+#
+class TextManager(QObject):
+
+ def __init__(self, parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+
+ self._change_log_text = ""
+
+ @pyqtSlot(result = str)
+ def getChangeLogText(self) -> str:
+ if not self._change_log_text:
+ self._change_log_text = self._loadChangeLogText()
+ return self._change_log_text
+
+ def _loadChangeLogText(self) -> str:
+ # Load change log texts and organize them with a dict
+ file_path = Resources.getPath(Resources.Texts, "change_log.txt")
+ change_logs_dict = {} # type: Dict[Version, Dict[str, List[str]]]
+ with open(file_path, "r", encoding = "utf-8") as f:
+ open_version = None # type: Optional[Version]
+ open_header = "" # Initialise to an empty header in case there is no "*" in the first line of the changelog
+ for line in f:
+ line = line.replace("\n", "")
+ if "[" in line and "]" in line:
+ line = line.replace("[", "")
+ line = line.replace("]", "")
+ open_version = Version(line)
+ if open_version > Version([14, 99, 99]): # Bit of a hack: We released the 15.x.x versions before 2.x
+ open_version = Version([0, open_version.getMinor(), open_version.getRevision(), open_version.getPostfixVersion()])
+ open_header = ""
+ change_logs_dict[open_version] = collections.OrderedDict()
+ elif line.startswith("*"):
+ open_header = line.replace("*", "")
+ change_logs_dict[cast(Version, open_version)][open_header] = []
+ elif line != "":
+ if open_header not in change_logs_dict[cast(Version, open_version)]:
+ change_logs_dict[cast(Version, open_version)][open_header] = []
+ change_logs_dict[cast(Version, open_version)][open_header].append(line)
+
+ # Format changelog text
+ content = ""
+ for version in sorted(change_logs_dict.keys(), reverse = True):
+ text_version = version
+ if version < Version([1, 0, 0]): # Bit of a hack: We released the 15.x.x versions before 2.x
+ text_version = Version([15, version.getMinor(), version.getRevision(), version.getPostfixVersion()])
+ content += "
" + str(text_version) + "
"
+ content += ""
+ for change in change_logs_dict[version]:
+ if str(change) != "":
+ content += "" + str(change) + " "
+ for line in change_logs_dict[version][change]:
+ content += str(line) + " "
+ content += " "
+
+ return content
diff --git a/cura/UI/WelcomePagesModel.py b/cura/UI/WelcomePagesModel.py
new file mode 100644
index 0000000000..c16ec3763e
--- /dev/null
+++ b/cura/UI/WelcomePagesModel.py
@@ -0,0 +1,294 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from collections import deque
+import os
+from typing import TYPE_CHECKING, Optional, List, Dict, Any
+
+from PyQt5.QtCore import QUrl, Qt, pyqtSlot, pyqtProperty, pyqtSignal
+
+from UM.i18n import i18nCatalog
+from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+from UM.Resources import Resources
+
+if TYPE_CHECKING:
+ from PyQt5.QtCore import QObject
+ from cura.CuraApplication import CuraApplication
+
+
+#
+# This is the Qt ListModel that contains all welcome pages data. Each page is a page that can be shown as a step in the
+# welcome wizard dialog. Each item in this ListModel represents a page, which contains the following fields:
+#
+# - id : A unique page_id which can be used in function goToPage(page_id)
+# - page_url : The QUrl to the QML file that contains the content of this page
+# - next_page_id : (OPTIONAL) The next page ID to go to when this page finished. This is optional. If this is not
+# provided, it will go to the page with the current index + 1
+# - next_page_button_text: (OPTIONAL) The text to show for the "next" button, by default it's the translated text of
+# "Next". Note that each step QML can decide whether to use this text or not, so it's not
+# mandatory.
+# - should_show_function : (OPTIONAL) An optional function that returns True/False indicating if this page should be
+# shown. By default all pages should be shown. If a function returns False, that page will
+# be skipped and its next page will be shown.
+#
+# Note that in any case, a page that has its "should_show_function" == False will ALWAYS be skipped.
+#
+class WelcomePagesModel(ListModel):
+
+ IdRole = Qt.UserRole + 1 # Page ID
+ PageUrlRole = Qt.UserRole + 2 # URL to the page's QML file
+ NextPageIdRole = Qt.UserRole + 3 # The next page ID it should go to
+ NextPageButtonTextRole = Qt.UserRole + 4 # The text for the next page button
+ PreviousPageButtonTextRole = Qt.UserRole + 5 # The text for the previous page button
+
+ def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent)
+
+ self.addRoleName(self.IdRole, "id")
+ self.addRoleName(self.PageUrlRole, "page_url")
+ self.addRoleName(self.NextPageIdRole, "next_page_id")
+ self.addRoleName(self.NextPageButtonTextRole, "next_page_button_text")
+ self.addRoleName(self.PreviousPageButtonTextRole, "previous_page_button_text")
+
+ self._application = application
+ self._catalog = i18nCatalog("cura")
+
+ self._default_next_button_text = self._catalog.i18nc("@action:button", "Next")
+
+ self._pages = [] # type: List[Dict[str, Any]]
+
+ self._current_page_index = 0
+ # Store all the previous page indices so it can go back.
+ self._previous_page_indices_stack = deque() # type: deque
+
+ # If the welcome flow should be shown. It can show the complete flow or just the changelog depending on the
+ # specific case. See initialize() for how this variable is set.
+ self._should_show_welcome_flow = False
+
+ allFinished = pyqtSignal() # emitted when all steps have been finished
+ currentPageIndexChanged = pyqtSignal()
+
+ @pyqtProperty(int, notify = currentPageIndexChanged)
+ def currentPageIndex(self) -> int:
+ return self._current_page_index
+
+ # Returns a float number in [0, 1] which indicates the current progress.
+ @pyqtProperty(float, notify = currentPageIndexChanged)
+ def currentProgress(self) -> float:
+ if len(self._items) == 0:
+ return 0
+ else:
+ return self._current_page_index / len(self._items)
+
+ # Indicates if the current page is the last page.
+ @pyqtProperty(bool, notify = currentPageIndexChanged)
+ def isCurrentPageLast(self) -> bool:
+ return self._current_page_index == len(self._items) - 1
+
+ def _setCurrentPageIndex(self, page_index: int) -> None:
+ if page_index != self._current_page_index:
+ self._previous_page_indices_stack.append(self._current_page_index)
+ self._current_page_index = page_index
+ self.currentPageIndexChanged.emit()
+
+ # Ends the Welcome-Pages. Put as a separate function for cases like the 'decline' in the User-Agreement.
+ @pyqtSlot()
+ def atEnd(self) -> None:
+ self.allFinished.emit()
+ self.resetState()
+
+ # Goes to the next page.
+ # If "from_index" is given, it will look for the next page to show starting from the "from_index" page instead of
+ # the "self._current_page_index".
+ @pyqtSlot()
+ def goToNextPage(self, from_index: Optional[int] = None) -> None:
+ # Look for the next page that should be shown
+ current_index = self._current_page_index if from_index is None else from_index
+ while True:
+ page_item = self._items[current_index]
+
+ # Check if there's a "next_page_id" assigned. If so, go to that page. Otherwise, go to the page with the
+ # current index + 1.
+ next_page_id = page_item.get("next_page_id")
+ next_page_index = current_index + 1
+ if next_page_id:
+ idx = self.getPageIndexById(next_page_id)
+ if idx is None:
+ # FIXME: If we cannot find the next page, we cannot do anything here.
+ Logger.log("e", "Cannot find page with ID [%s]", next_page_id)
+ return
+ next_page_index = idx
+
+ # If we have reached the last page, emit allFinished signal and reset.
+ if next_page_index == len(self._items):
+ self.atEnd()
+ return
+
+ # Check if the this page should be shown (default yes), if not, keep looking for the next one.
+ next_page_item = self.getItem(next_page_index)
+ if self._shouldPageBeShown(next_page_index):
+ break
+
+ Logger.log("d", "Page [%s] should not be displayed, look for the next page.", next_page_item["id"])
+ current_index = next_page_index
+
+ # Move to the next page
+ self._setCurrentPageIndex(next_page_index)
+
+ # Goes to the previous page. If there's no previous page, do nothing.
+ @pyqtSlot()
+ def goToPreviousPage(self) -> None:
+ if len(self._previous_page_indices_stack) == 0:
+ Logger.log("i", "No previous page, do nothing")
+ return
+
+ previous_page_index = self._previous_page_indices_stack.pop()
+ self._current_page_index = previous_page_index
+ self.currentPageIndexChanged.emit()
+
+ # Sets the current page to the given page ID. If the page ID is not found, do nothing.
+ @pyqtSlot(str)
+ def goToPage(self, page_id: str) -> None:
+ page_index = self.getPageIndexById(page_id)
+ if page_index is None:
+ # FIXME: If we cannot find the next page, we cannot do anything here.
+ Logger.log("e", "Cannot find page with ID [%s], go to the next page by default", page_index)
+ self.goToNextPage()
+ return
+
+ if self._shouldPageBeShown(page_index):
+ # Move to that page if it should be shown
+ self._setCurrentPageIndex(page_index)
+ else:
+ # Find the next page to show starting from the "page_index"
+ self.goToNextPage(from_index = page_index)
+
+ # Checks if the page with the given index should be shown by calling the "should_show_function" associated with it.
+ # If the function is not present, returns True (show page by default).
+ def _shouldPageBeShown(self, page_index: int) -> bool:
+ next_page_item = self.getItem(page_index)
+ should_show_function = next_page_item.get("should_show_function", lambda: True)
+ return should_show_function()
+
+ # Resets the state of the WelcomePagesModel. This functions does the following:
+ # - Resets current_page_index to 0
+ # - Clears the previous page indices stack
+ @pyqtSlot()
+ def resetState(self) -> None:
+ self._current_page_index = 0
+ self._previous_page_indices_stack.clear()
+
+ self.currentPageIndexChanged.emit()
+
+ shouldShowWelcomeFlowChanged = pyqtSignal()
+
+ @pyqtProperty(bool, notify = shouldShowWelcomeFlowChanged)
+ def shouldShowWelcomeFlow(self) -> bool:
+ return self._should_show_welcome_flow
+
+ # Gets the page index with the given page ID. If the page ID doesn't exist, returns None.
+ def getPageIndexById(self, page_id: str) -> Optional[int]:
+ page_idx = None
+ for idx, page_item in enumerate(self._items):
+ if page_item["id"] == page_id:
+ page_idx = idx
+ break
+ return page_idx
+
+ # Convenience function to get QUrl path to pages that's located in "resources/qml/WelcomePages".
+ def _getBuiltinWelcomePagePath(self, page_filename: str) -> "QUrl":
+ from cura.CuraApplication import CuraApplication
+ return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
+ os.path.join("WelcomePages", page_filename)))
+
+ # FIXME: HACKs for optimization that we don't update the model every time the active machine gets changed.
+ def _onActiveMachineChanged(self) -> None:
+ self._application.getMachineManager().globalContainerChanged.disconnect(self._onActiveMachineChanged)
+ self._initialize(update_should_show_flag = False)
+
+ def initialize(self) -> None:
+ self._application.getMachineManager().globalContainerChanged.connect(self._onActiveMachineChanged)
+ self._initialize()
+
+ def _initialize(self, update_should_show_flag: bool = True) -> None:
+ show_whatsnew_only = False
+ if update_should_show_flag:
+ has_active_machine = self._application.getMachineManager().activeMachine is not None
+ has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion()
+
+ # Only show the what's new dialog if there's no machine and we have just upgraded
+ show_complete_flow = not has_active_machine
+ show_whatsnew_only = has_active_machine and has_app_just_upgraded
+
+ # FIXME: This is a hack. Because of the circular dependency between MachineManager, ExtruderManager, and
+ # possibly some others, setting the initial active machine is not done when the MachineManager gets initialized.
+ # So at this point, we don't know if there will be an active machine or not. It could be that the active machine
+ # files are corrupted so we cannot rely on Preferences either. This makes sure that once the active machine
+ # gets changed, this model updates the flags, so it can decide whether to show the welcome flow or not.
+ should_show_welcome_flow = show_complete_flow or show_whatsnew_only
+ if should_show_welcome_flow != self._should_show_welcome_flow:
+ self._should_show_welcome_flow = should_show_welcome_flow
+ self.shouldShowWelcomeFlowChanged.emit()
+
+ # All pages
+ all_pages_list = [{"id": "welcome",
+ "page_url": self._getBuiltinWelcomePagePath("WelcomeContent.qml"),
+ },
+ {"id": "user_agreement",
+ "page_url": self._getBuiltinWelcomePagePath("UserAgreementContent.qml"),
+ },
+ {"id": "whats_new",
+ "page_url": self._getBuiltinWelcomePagePath("WhatsNewContent.qml"),
+ },
+ {"id": "data_collections",
+ "page_url": self._getBuiltinWelcomePagePath("DataCollectionsContent.qml"),
+ },
+ {"id": "add_network_or_local_printer",
+ "page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"),
+ "next_page_id": "machine_actions",
+ },
+ {"id": "add_printer_by_ip",
+ "page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"),
+ "next_page_id": "machine_actions",
+ },
+ {"id": "machine_actions",
+ "page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
+ "next_page_id": "cloud",
+ "should_show_function": self.shouldShowMachineActions,
+ },
+ {"id": "cloud",
+ "page_url": self._getBuiltinWelcomePagePath("CloudContent.qml"),
+ },
+ ]
+
+ pages_to_show = all_pages_list
+ if show_whatsnew_only:
+ pages_to_show = list(filter(lambda x: x["id"] == "whats_new", all_pages_list))
+
+ self._pages = pages_to_show
+ self.setItems(self._pages)
+
+ # For convenience, inject the default "next" button text to each item if it's not present.
+ def setItems(self, items: List[Dict[str, Any]]) -> None:
+ for item in items:
+ if "next_page_button_text" not in item:
+ item["next_page_button_text"] = self._default_next_button_text
+
+ super().setItems(items)
+
+ # Indicates if the machine action panel should be shown by checking if there's any first start machine actions
+ # available.
+ def shouldShowMachineActions(self) -> bool:
+ global_stack = self._application.getMachineManager().activeMachine
+ if global_stack is None:
+ return False
+
+ definition_id = global_stack.definition.getId()
+ first_start_actions = self._application.getMachineActionManager().getFirstStartActions(definition_id)
+ return len([action for action in first_start_actions if action.needsUserInteraction()]) > 0
+
+ def addPage(self) -> None:
+ pass
+
+
+__all__ = ["WelcomePagesModel"]
diff --git a/cura/UI/WhatsNewPagesModel.py b/cura/UI/WhatsNewPagesModel.py
new file mode 100644
index 0000000000..5b968ae574
--- /dev/null
+++ b/cura/UI/WhatsNewPagesModel.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from .WelcomePagesModel import WelcomePagesModel
+
+
+#
+# This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for showing the
+# "what's new" page. This is also used in the "Help" menu to show the changes log.
+#
+class WhatsNewPagesModel(WelcomePagesModel):
+
+ def initialize(self) -> None:
+ self._pages = []
+ self._pages.append({"id": "whats_new",
+ "page_url": self._getBuiltinWelcomePagePath("WhatsNewContent.qml"),
+ "next_page_button_text": self._catalog.i18nc("@action:button", "Close"),
+ })
+ self.setItems(self._pages)
+
+
+__all__ = ["WhatsNewPagesModel"]
diff --git a/cura/UI/__init__.py b/cura/UI/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/cura/Utils/Decorators.py b/cura/Utils/Decorators.py
new file mode 100644
index 0000000000..9275ee6ce9
--- /dev/null
+++ b/cura/Utils/Decorators.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import functools
+import re
+from typing import Callable
+
+# An API version must be a semantic version "x.y.z" where ".z" is optional. So the valid formats are as follows:
+# - x.y.z
+# - x.y
+SEMANTIC_VERSION_REGEX = re.compile(r"^[0-9]+\.[0-9]+(\.[0-9]+)?$")
+
+
+## Decorator for functions that belong to a set of APIs. For now, this should only be used for officially supported
+# APIs, meaning that those APIs should be versioned and maintained.
+#
+# \param since_version The earliest version since when this API becomes supported. This means that since this version,
+# this API function is supposed to behave the same. This parameter is not used. It's just a
+# documentation.
+def api(since_version: str) -> Callable:
+ # Make sure that APi versions are semantic versions
+ if not SEMANTIC_VERSION_REGEX.fullmatch(since_version):
+ raise ValueError("API since_version [%s] is not a semantic version." % since_version)
+
+ def api_decorator(function):
+ @functools.wraps(function)
+ def api_wrapper(*args, **kwargs):
+ return function(*args, **kwargs)
+ return api_wrapper
+ return api_decorator
diff --git a/cura/Utils/NetworkingUtil.py b/cura/Utils/NetworkingUtil.py
new file mode 100644
index 0000000000..b13f7903b9
--- /dev/null
+++ b/cura/Utils/NetworkingUtil.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import socket
+from typing import Optional
+
+from PyQt5.QtCore import QObject, pyqtSlot
+
+
+#
+# This is a QObject because some of the functions can be used (and are useful) in QML.
+#
+class NetworkingUtil(QObject):
+
+ def __init__(self, parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent = parent)
+
+ # Checks if the given string is a valid IPv4 address.
+ @pyqtSlot(str, result = bool)
+ def isIPv4(self, address: str) -> bool:
+ try:
+ socket.inet_pton(socket.AF_INET, address)
+ result = True
+ except:
+ result = False
+ return result
+
+ # Checks if the given string is a valid IPv6 address.
+ @pyqtSlot(str, result = bool)
+ def isIPv6(self, address: str) -> bool:
+ try:
+ socket.inet_pton(socket.AF_INET6, address)
+ result = True
+ except:
+ result = False
+ return result
+
+ # Checks if the given string is a valid IPv4 or IPv6 address.
+ @pyqtSlot(str, result = bool)
+ def isValidIP(self, address: str) -> bool:
+ return self.isIPv4(address) or self.isIPv6(address)
+
+
+__all__ = ["NetworkingUtil"]
diff --git a/cura_app.py b/cura_app.py
index 3224a5b99b..e14b4410bc 100755
--- a/cura_app.py
+++ b/cura_app.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import argparse
@@ -23,13 +23,17 @@ known_args = vars(parser.parse_known_args()[0])
if not known_args["debug"]:
def get_cura_dir_path():
if Platform.isWindows():
- return os.path.expanduser("~/AppData/Roaming/" + CuraAppName)
+ appdata_path = os.getenv("APPDATA")
+ if not appdata_path: #Defensive against the environment variable missing (should never happen).
+ appdata_path = "."
+ return os.path.join(appdata_path, CuraAppName)
elif Platform.isLinux():
return os.path.expanduser("~/.local/share/" + CuraAppName)
elif Platform.isOSX():
return os.path.expanduser("~/Library/Logs/" + CuraAppName)
- if hasattr(sys, "frozen"):
+ # Do not redirect stdout and stderr to files if we are running CLI.
+ if hasattr(sys, "frozen") and "cli" not in os.path.basename(sys.argv[0]).lower():
dirpath = get_cura_dir_path()
os.makedirs(dirpath, exist_ok = True)
sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding = "utf-8")
@@ -56,6 +60,14 @@ if Platform.isWindows() and hasattr(sys, "frozen"):
except KeyError:
pass
+# GITHUB issue #6194: https://github.com/Ultimaker/Cura/issues/6194
+# With AppImage 2 on Linux, the current working directory will be somewhere in /tmp//usr, which is owned
+# by root. For some reason, QDesktopServices.openUrl() requires to have a usable current working directory,
+# otherwise it doesn't work. This is a workaround on Linux that before we call QDesktopServices.openUrl(), we
+# switch to a directory where the user has the ownership.
+if Platform.isLinux() and hasattr(sys, "frozen"):
+ os.chdir(os.path.expanduser("~"))
+
# WORKAROUND: GITHUB-704 GITHUB-708
# It looks like setuptools creates a .pth file in
# the default /usr/lib which causes the default site-packages
@@ -119,7 +131,10 @@ def exceptHook(hook_type, value, traceback):
# Set exception hook to use the crash dialog handler
sys.excepthook = exceptHook
# Enable dumping traceback for all threads
-faulthandler.enable(all_threads = True)
+if sys.stderr:
+ faulthandler.enable(file = sys.stderr, all_threads = True)
+else:
+ faulthandler.enable(file = sys.stdout, all_threads = True)
# Workaround for a race condition on certain systems where there
# is a race condition between Arcus and PyQt. Importing Arcus
@@ -129,5 +144,37 @@ import Arcus #@UnusedImport
import Savitar #@UnusedImport
from cura.CuraApplication import CuraApplication
+
+# WORKAROUND: CURA-6739
+# The CTM file loading module in Trimesh requires the OpenCTM library to be dynamically loaded. It uses
+# ctypes.util.find_library() to find libopenctm.dylib, but this doesn't seem to look in the ".app" application folder
+# on Mac OS X. Adding the search path to environment variables such as DYLD_LIBRARY_PATH and DYLD_FALLBACK_LIBRARY_PATH
+# makes it work. The workaround here uses DYLD_FALLBACK_LIBRARY_PATH.
+if Platform.isOSX() and getattr(sys, "frozen", False):
+ old_env = os.environ.get("DYLD_FALLBACK_LIBRARY_PATH", "")
+ # This is where libopenctm.so is in the .app folder.
+ search_path = os.path.join(CuraApplication.getInstallPrefix(), "MacOS")
+ path_list = old_env.split(":")
+ if search_path not in path_list:
+ path_list.append(search_path)
+ os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = ":".join(path_list)
+ import trimesh.exchange.load
+ os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = old_env
+
+# WORKAROUND: CURA-6739
+# Similar CTM file loading fix for Linux, but NOTE THAT this doesn't work directly with Python 3.5.7. There's a fix
+# for ctypes.util.find_library() in Python 3.6 and 3.7. That fix makes sure that find_library() will check
+# LD_LIBRARY_PATH. With Python 3.5, that fix needs to be backported to make this workaround work.
+if Platform.isLinux() and getattr(sys, "frozen", False):
+ old_env = os.environ.get("LD_LIBRARY_PATH", "")
+ # This is where libopenctm.so is in the AppImage.
+ search_path = os.path.join(CuraApplication.getInstallPrefix(), "bin")
+ path_list = old_env.split(":")
+ if search_path not in path_list:
+ path_list.append(search_path)
+ os.environ["LD_LIBRARY_PATH"] = ":".join(path_list)
+ import trimesh.exchange.load
+ os.environ["LD_LIBRARY_PATH"] = old_env
+
app = CuraApplication()
app.run()
diff --git a/docker/build.sh b/docker/build.sh
new file mode 100755
index 0000000000..eb20b18c0d
--- /dev/null
+++ b/docker/build.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+# Abort at the first error.
+set -e
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+PROJECT_DIR="$( cd "${SCRIPT_DIR}/.." && pwd )"
+
+# Make sure that environment variables are set properly
+source /opt/rh/devtoolset-7/enable
+export PATH="${CURA_BUILD_ENV_PATH}/bin:${PATH}"
+export PKG_CONFIG_PATH="${CURA_BUILD_ENV_PATH}/lib/pkgconfig:${PKG_CONFIG_PATH}"
+
+cd "${PROJECT_DIR}"
+
+#
+# Clone Uranium and set PYTHONPATH first
+#
+
+# Check the branch to use:
+# 1. Use the Uranium branch with the branch same if it exists.
+# 2. Otherwise, use the default branch name "master"
+URANIUM_BRANCH="${CI_COMMIT_REF_NAME:-master}"
+output="$(git ls-remote --heads https://github.com/Ultimaker/Uranium.git "${URANIUM_BRANCH}")"
+if [ -z "${output}" ]; then
+ echo "Could not find Uranium banch ${URANIUM_BRANCH}, fallback to use master."
+ URANIUM_BRANCH="master"
+fi
+
+echo "Using Uranium branch ${URANIUM_BRANCH} ..."
+git clone --depth=1 -b "${URANIUM_BRANCH}" https://github.com/Ultimaker/Uranium.git "${PROJECT_DIR}"/Uranium
+export PYTHONPATH="${PROJECT_DIR}/Uranium:.:${PYTHONPATH}"
+
+mkdir build
+cd build
+cmake3 \
+ -DCMAKE_BUILD_TYPE=Debug \
+ -DCMAKE_PREFIX_PATH="${CURA_BUILD_ENV_PATH}" \
+ -DURANIUM_DIR="${PROJECT_DIR}/Uranium" \
+ -DBUILD_TESTS=ON \
+ ..
+make
+ctest3 --output-on-failure -T Test
diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py
index 49c6995d18..20eb9b29dc 100755
--- a/plugins/3MFReader/ThreeMFReader.py
+++ b/plugins/3MFReader/ThreeMFReader.py
@@ -1,7 +1,7 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional
+from typing import List, Optional, Union, TYPE_CHECKING
import os.path
import zipfile
@@ -9,27 +9,26 @@ import numpy
import Savitar
-from UM.Application import Application
from UM.Logger import Logger
from UM.Math.Matrix import Matrix
from UM.Math.Vector import Vector
from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Mesh.MeshReader import MeshReader
from UM.Scene.GroupDecorator import GroupDecorator
+from UM.Scene.SceneNode import SceneNode #For typing.
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
+from cura.CuraApplication import CuraApplication
+from cura.Machines.ContainerTree import ContainerTree
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
from cura.Scene.ZOffsetDecorator import ZOffsetDecorator
-from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
-
-MYPY = False
try:
- if not MYPY:
+ if not TYPE_CHECKING:
import xml.etree.cElementTree as ET
except ImportError:
Logger.log("w", "Unable to load cElementTree, switching to slower version")
@@ -55,7 +54,7 @@ class ThreeMFReader(MeshReader):
self._unit = None
self._object_count = 0 # Used to name objects as there is no node name yet.
- def _createMatrixFromTransformationString(self, transformation):
+ def _createMatrixFromTransformationString(self, transformation: str) -> Matrix:
if transformation == "":
return Matrix()
@@ -85,13 +84,13 @@ class ThreeMFReader(MeshReader):
return temp_mat
- ## Convenience function that converts a SceneNode object (as obtained from libSavitar) to a Uranium scene node.
- # \returns Uranium scene node.
- def _convertSavitarNodeToUMNode(self, savitar_node):
+ ## Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node.
+ # \returns Scene node.
+ def _convertSavitarNodeToUMNode(self, savitar_node: Savitar.SceneNode) -> Optional[SceneNode]:
self._object_count += 1
node_name = "Object %s" % self._object_count
- active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
+ active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
um_node = CuraSceneNode() # This adds a SettingOverrideDecorator
um_node.addDecorator(BuildPlateDecorator(active_build_plate))
@@ -122,7 +121,7 @@ class ThreeMFReader(MeshReader):
# Add the setting override decorator, so we can add settings to this node.
if settings:
- global_container_stack = Application.getInstance().getGlobalContainerStack()
+ global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
# Ensure the correct next container for the SettingOverride decorator is set.
if global_container_stack:
@@ -132,7 +131,7 @@ class ThreeMFReader(MeshReader):
um_node.callDecoration("setActiveExtruder", default_stack.getId())
# Get the definition & set it
- definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition)
+ definition_id = ContainerTree.getInstance().machines[global_container_stack.definition.getId()].quality_definition
um_node.callDecoration("getStack").getTop().setDefinition(definition_id)
setting_container = um_node.callDecoration("getStack").getTop()
@@ -161,7 +160,7 @@ class ThreeMFReader(MeshReader):
um_node.addDecorator(sliceable_decorator)
return um_node
- def _read(self, file_name):
+ def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]:
result = []
self._object_count = 0 # Used to name objects as there is no node name yet.
# The base object of 3mf is a zipped archive.
@@ -181,12 +180,13 @@ class ThreeMFReader(MeshReader):
mesh_data = um_node.getMeshData()
if mesh_data is not None:
extents = mesh_data.getExtents()
- center_vector = Vector(extents.center.x, extents.center.y, extents.center.z)
- transform_matrix.setByTranslation(center_vector)
+ if extents is not None:
+ center_vector = Vector(extents.center.x, extents.center.y, extents.center.z)
+ transform_matrix.setByTranslation(center_vector)
transform_matrix.multiply(um_node.getLocalTransformation())
um_node.setTransformation(transform_matrix)
- global_container_stack = Application.getInstance().getGlobalContainerStack()
+ global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
# Create a transformation Matrix to convert from 3mf worldspace into ours.
# First step: flip the y and z axis.
@@ -215,17 +215,20 @@ class ThreeMFReader(MeshReader):
um_node.setTransformation(um_node.getLocalTransformation().preMultiply(transformation_matrix))
# Check if the model is positioned below the build plate and honor that when loading project files.
- if um_node.getMeshData() is not None:
- minimum_z_value = um_node.getMeshData().getExtents(um_node.getWorldTransformation()).minimum.y # y is z in transformation coordinates
- if minimum_z_value < 0:
- um_node.addDecorator(ZOffsetDecorator())
- um_node.callDecoration("setZOffset", minimum_z_value)
+ node_meshdata = um_node.getMeshData()
+ if node_meshdata is not None:
+ aabb = node_meshdata.getExtents(um_node.getWorldTransformation())
+ if aabb is not None:
+ minimum_z_value = aabb.minimum.y # y is z in transformation coordinates
+ if minimum_z_value < 0:
+ um_node.addDecorator(ZOffsetDecorator())
+ um_node.callDecoration("setZOffset", minimum_z_value)
result.append(um_node)
except Exception:
Logger.logException("e", "An exception occurred in 3mf reader.")
- return None
+ return []
return result
diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py
index 38652361a5..dd35484c31 100755
--- a/plugins/3MFReader/ThreeMFWorkspaceReader.py
+++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py
@@ -1,10 +1,10 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from configparser import ConfigParser
import zipfile
import os
-from typing import Dict, List, Tuple, cast
+from typing import cast, Dict, List, Optional, Tuple
import xml.etree.ElementTree as ET
@@ -14,7 +14,6 @@ from UM.Application import Application
from UM.Logger import Logger
from UM.Message import Message
from UM.i18n import i18nCatalog
-from UM.Signal import postponeSignals, CompressTechnique
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer
@@ -24,22 +23,25 @@ from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
from UM.Job import Job
from UM.Preferences import Preferences
-from cura.Machines.VariantType import VariantType
+from cura.Machines.ContainerTree import ContainerTree
from cura.Settings.CuraStackBuilder import CuraStackBuilder
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.ExtruderStack import ExtruderStack
from cura.Settings.GlobalStack import GlobalStack
+from cura.Settings.IntentManager import IntentManager
from cura.Settings.CuraContainerStack import _ContainerIndexes
from cura.CuraApplication import CuraApplication
from cura.Utils.Threading import call_on_qt_thread
+from PyQt5.QtCore import QCoreApplication
+
from .WorkspaceDialog import WorkspaceDialog
i18n_catalog = i18nCatalog("cura")
class ContainerInfo:
- def __init__(self, file_name: str, serialized: str, parser: ConfigParser) -> None:
+ def __init__(self, file_name: Optional[str], serialized: Optional[str], parser: Optional[ConfigParser]) -> None:
self.file_name = file_name
self.serialized = serialized
self.parser = parser
@@ -59,7 +61,11 @@ class MachineInfo:
self.container_id = None
self.name = None
self.definition_id = None
+
+ self.metadata_dict = {} # type: Dict[str, str]
+
self.quality_type = None
+ self.intent_category = None
self.custom_quality_name = None
self.quality_changes_info = None
self.variant_info = None
@@ -79,6 +85,7 @@ class ExtruderInfo:
self.definition_changes_info = None
self.user_changes_info = None
+ self.intent_info = None
## Base implementation for reading 3MF workspace files.
@@ -227,6 +234,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
else:
Logger.log("w", "Unknown definition container type %s for %s",
definition_container_type, definition_container_file)
+ QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
Job.yieldThread()
if machine_definition_container_count != 1:
@@ -253,13 +261,16 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
containers_found_dict["material"] = True
if not self._container_registry.isReadOnly(container_id): # Only non readonly materials can be in conflict
material_conflict = True
+ QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
Job.yieldThread()
# Check if any quality_changes instance container is in conflict.
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
quality_name = ""
custom_quality_name = ""
- num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
+ intent_name = ""
+ intent_category = ""
+ num_settings_overridden_by_quality_changes = 0 # How many settings are changed by the quality changes
num_user_settings = 0
quality_changes_conflict = False
@@ -297,7 +308,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
custom_quality_name = parser["general"]["name"]
values = parser["values"] if parser.has_section("values") else dict()
- num_settings_overriden_by_quality_changes += len(values)
+ num_settings_overridden_by_quality_changes += len(values)
# Check if quality changes already exists.
quality_changes = self._container_registry.findInstanceContainers(name = custom_quality_name,
type = "quality_changes")
@@ -316,13 +327,17 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
elif container_type == "quality":
if not quality_name:
quality_name = parser["general"]["name"]
+ elif container_type == "intent":
+ if not intent_name:
+ intent_name = parser["general"]["name"]
+ intent_category = parser["metadata"]["intent_category"]
elif container_type == "user":
num_user_settings += len(parser["values"])
elif container_type in self._ignored_instance_container_types:
# Ignore certain instance container types
Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type)
continue
-
+ QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
Job.yieldThread()
if self._machine_info.quality_changes_info.global_info is None:
@@ -341,7 +356,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# To simplify this, only check if the global stack exists or not
global_stack_id = self._stripFileToId(global_stack_file)
serialized = archive.open(global_stack_file).read().decode("utf-8")
+ serialized = GlobalStack._updateSerialized(serialized, global_stack_file)
machine_name = self._getMachineNameFromSerializedStack(serialized)
+ self._machine_info.metadata_dict = self._getMetaDataDictFromSerializedStack(serialized)
+
stacks = self._container_registry.findContainerStacks(name = machine_name, type = "machine")
self._is_same_machine_type = True
existing_global_stack = None
@@ -397,7 +415,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
variant_id = parser["containers"][str(_ContainerIndexes.Variant)]
if variant_id not in ("empty", "empty_variant"):
self._machine_info.variant_info = instance_container_info_dict[variant_id]
-
+ QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
Job.yieldThread()
# if the global stack is found, we check if there are conflicts in the extruder stacks
@@ -419,18 +437,26 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if parser.has_option("metadata", "enabled"):
extruder_info.enabled = parser["metadata"]["enabled"]
if variant_id not in ("empty", "empty_variant"):
- extruder_info.variant_info = instance_container_info_dict[variant_id]
+ if variant_id in instance_container_info_dict:
+ extruder_info.variant_info = instance_container_info_dict[variant_id]
+
if material_id not in ("empty", "empty_material"):
root_material_id = reverse_material_id_dict[material_id]
extruder_info.root_material_id = root_material_id
+
definition_changes_id = parser["containers"][str(_ContainerIndexes.DefinitionChanges)]
if definition_changes_id not in ("empty", "empty_definition_changes"):
extruder_info.definition_changes_info = instance_container_info_dict[definition_changes_id]
+
user_changes_id = parser["containers"][str(_ContainerIndexes.UserChanges)]
if user_changes_id not in ("empty", "empty_user_changes"):
extruder_info.user_changes_info = instance_container_info_dict[user_changes_id]
self._machine_info.extruder_info_dict[position] = extruder_info
+ intent_id = parser["containers"][str(_ContainerIndexes.Intent)]
+ if intent_id not in ("empty", "empty_intent"):
+ extruder_info.intent_info = instance_container_info_dict[intent_id]
+
if not machine_conflict and containers_found_dict["machine"]:
if position not in global_stack.extruders:
continue
@@ -495,6 +521,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._machine_info.definition_id = machine_definition_id
self._machine_info.quality_type = quality_type
self._machine_info.custom_quality_name = quality_name
+ self._machine_info.intent_category = intent_category
if machine_conflict and not self._is_same_machine_type:
machine_conflict = False
@@ -515,7 +542,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._dialog.setNumVisibleSettings(num_visible_settings)
self._dialog.setQualityName(quality_name)
self._dialog.setQualityType(quality_type)
- self._dialog.setNumSettingsOverridenByQualityChanges(num_settings_overriden_by_quality_changes)
+ self._dialog.setIntentName(intent_name)
+ self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes)
self._dialog.setNumUserSettings(num_user_settings)
self._dialog.setActiveMode(active_mode)
self._dialog.setMachineName(machine_name)
@@ -558,26 +586,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# \param file_name
@call_on_qt_thread
def read(self, file_name):
- container_registry = ContainerRegistry.getInstance()
- signals = [container_registry.containerAdded,
- container_registry.containerRemoved,
- container_registry.containerMetaDataChanged]
- #
- # We now have different managers updating their lookup tables upon container changes. It is critical to make
- # sure that the managers have a complete set of data when they update.
- #
- # In project loading, lots of the container-related signals are loosely emitted, which can create timing gaps
- # for incomplete data update or other kinds of issues to happen.
- #
- # To avoid this, we postpone all signals so they don't get emitted immediately. But, please also be aware that,
- # because of this, do not expect to have the latest data in the lookup tables in project loading.
- #
- with postponeSignals(*signals, compress = CompressTechnique.NoCompression):
- return self._read(file_name)
-
- def _read(self, file_name):
application = CuraApplication.getInstance()
- material_manager = application.getMaterialManager()
archive = zipfile.ZipFile(file_name, "r")
@@ -648,6 +657,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
definition_container = self._container_registry.findDefinitionContainers(id = "fdmprinter")[0] #Fall back to defaults.
self._container_registry.addContainer(definition_container)
Job.yieldThread()
+ QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
Logger.log("d", "Workspace loading is checking materials...")
# Get all the material files and check if they exist. If not, add them.
@@ -674,7 +684,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if self._resolve_strategies["material"] == "override":
# Remove the old materials and then deserialize the one from the project
root_material_id = material_container.getMetaDataEntry("base_file")
- material_manager.removeMaterialByRootId(root_material_id)
+ application.getContainerRegistry().removeContainer(root_material_id)
elif self._resolve_strategies["material"] == "new":
# Note that we *must* deserialize it with a new ID, as multiple containers will be
# auto created & added.
@@ -697,6 +707,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
material_container.setDirty(True)
self._container_registry.addContainer(material_container)
Job.yieldThread()
+ QCoreApplication.processEvents() # Ensure that the GUI does not freeze.
# Handle quality changes if any
self._processQualityChanges(global_stack)
@@ -727,9 +738,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if self._machine_info.quality_changes_info is None:
return
- application = CuraApplication.getInstance()
- quality_manager = application.getQualityManager()
-
# If we have custom profiles, load them
quality_changes_name = self._machine_info.quality_changes_info.name
if self._machine_info.quality_changes_info is not None:
@@ -737,12 +745,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._machine_info.quality_changes_info.name)
# Get the correct extruder definition IDs for quality changes
- from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
- machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(global_stack.definition)
+ machine_definition_id_for_quality = ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
machine_definition_for_quality = self._container_registry.findDefinitionContainers(id = machine_definition_id_for_quality)[0]
quality_changes_info = self._machine_info.quality_changes_info
quality_changes_quality_type = quality_changes_info.global_info.parser["metadata"]["quality_type"]
+ quality_changes_intent_category_per_extruder = {position: info.parser["metadata"].get("intent_category", "default") for position, info in quality_changes_info.extruder_info_dict.items()}
quality_changes_name = quality_changes_info.name
create_new = self._resolve_strategies.get("quality_changes") != "override"
@@ -753,13 +761,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
quality_changes_name = self._container_registry.uniqueName(quality_changes_name)
for position, container_info in container_info_dict.items():
extruder_stack = None
+ intent_category = None # type: Optional[str]
if position is not None:
extruder_stack = global_stack.extruders[position]
- container = quality_manager._createQualityChanges(quality_changes_quality_type,
- quality_changes_name,
- global_stack, extruder_stack)
+ intent_category = quality_changes_intent_category_per_extruder[position]
+ container = self._createNewQualityChanges(quality_changes_quality_type, intent_category, quality_changes_name, global_stack, extruder_stack)
container_info.container = container
- container.setDirty(True)
self._container_registry.addContainer(container)
Logger.log("d", "Created new quality changes container [%s]", container.getId())
@@ -787,11 +794,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if not global_stack.extruders:
ExtruderManager.getInstance().fixSingleExtrusionMachineExtruderDefinition(global_stack)
extruder_stack = global_stack.extruders["0"]
+ intent_category = quality_changes_intent_category_per_extruder["0"]
- container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
- global_stack, extruder_stack)
+ container = self._createNewQualityChanges(quality_changes_quality_type, intent_category, quality_changes_name, global_stack, extruder_stack)
container_info.container = container
- container.setDirty(True)
self._container_registry.addContainer(container)
Logger.log("d", "Created new quality changes container [%s]", container.getId())
@@ -817,16 +823,57 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if container_info.container is None:
extruder_stack = global_stack.extruders[position]
- container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
- global_stack, extruder_stack)
+ intent_category = quality_changes_intent_category_per_extruder[position]
+ container = self._createNewQualityChanges(quality_changes_quality_type, intent_category, quality_changes_name, global_stack, extruder_stack)
container_info.container = container
+ self._container_registry.addContainer(container)
for key, value in container_info.parser["values"].items():
container_info.container.setProperty(key, "value", value)
self._machine_info.quality_changes_info.name = quality_changes_name
- def _clearStack(self, stack):
+ ## Helper class to create a new quality changes profile.
+ #
+ # This will then later be filled with the appropriate data.
+ # \param quality_type The quality type of the new profile.
+ # \param intent_category The intent category of the new profile.
+ # \param name The name for the profile. This will later be made unique so
+ # it doesn't need to be unique yet.
+ # \param global_stack The global stack showing the configuration that the
+ # profile should be created for.
+ # \param extruder_stack The extruder stack showing the configuration that
+ # the profile should be created for. If this is None, it will be created
+ # for the global stack.
+ def _createNewQualityChanges(self, quality_type: str, intent_category: Optional[str], name: str, global_stack: GlobalStack, extruder_stack: Optional[ExtruderStack]) -> InstanceContainer:
+ container_registry = CuraApplication.getInstance().getContainerRegistry()
+ base_id = global_stack.definition.getId() if extruder_stack is None else extruder_stack.getId()
+ new_id = base_id + "_" + name
+ new_id = new_id.lower().replace(" ", "_")
+ new_id = container_registry.uniqueName(new_id)
+
+ # Create a new quality_changes container for the quality.
+ quality_changes = InstanceContainer(new_id)
+ quality_changes.setName(name)
+ quality_changes.setMetaDataEntry("type", "quality_changes")
+ quality_changes.setMetaDataEntry("quality_type", quality_type)
+ if intent_category is not None:
+ quality_changes.setMetaDataEntry("intent_category", intent_category)
+
+ # If we are creating a container for an extruder, ensure we add that to the container.
+ if extruder_stack is not None:
+ quality_changes.setMetaDataEntry("position", extruder_stack.getMetaDataEntry("position"))
+
+ # If the machine specifies qualities should be filtered, ensure we match the current criteria.
+ machine_definition_id = ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
+ quality_changes.setDefinition(machine_definition_id)
+
+ quality_changes.setMetaDataEntry("setting_version", CuraApplication.getInstance().SettingVersion)
+ quality_changes.setDirty(True)
+ return quality_changes
+
+ @staticmethod
+ def _clearStack(stack):
application = CuraApplication.getInstance()
stack.definitionChanges.clear()
@@ -885,41 +932,30 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
extruder_stack.userChanges.setProperty(key, "value", value)
def _applyVariants(self, global_stack, extruder_stack_dict):
- application = CuraApplication.getInstance()
- variant_manager = application.getVariantManager()
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
+ # Take the global variant from the machine info if available.
if self._machine_info.variant_info is not None:
- parser = self._machine_info.variant_info.parser
- variant_name = parser["general"]["name"]
-
- variant_type = VariantType.BUILD_PLATE
-
- node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type)
- if node is not None and node.getContainer() is not None:
- global_stack.variant = node.getContainer()
+ variant_name = self._machine_info.variant_info.parser["general"]["name"]
+ if variant_name in machine_node.variants:
+ global_stack.variant = machine_node.variants[variant_name].container
+ else:
+ Logger.log("w", "Could not find global variant '{0}'.".format(variant_name))
for position, extruder_stack in extruder_stack_dict.items():
if position not in self._machine_info.extruder_info_dict:
continue
extruder_info = self._machine_info.extruder_info_dict[position]
if extruder_info.variant_info is None:
- continue
- parser = extruder_info.variant_info.parser
-
- variant_name = parser["general"]["name"]
- variant_type = VariantType.NOZZLE
-
- node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type)
- if node is not None and node.getContainer() is not None:
- extruder_stack.variant = node.getContainer()
+ # If there is no variant_info, try to use the default variant. Otherwise, any available variant.
+ node = machine_node.variants.get(machine_node.preferred_variant_name, next(iter(machine_node.variants.values())))
+ else:
+ variant_name = extruder_info.variant_info.parser["general"]["name"]
+ node = ContainerTree.getInstance().machines[global_stack.definition.getId()].variants[variant_name]
+ extruder_stack.variant = node.container
def _applyMaterials(self, global_stack, extruder_stack_dict):
- application = CuraApplication.getInstance()
- material_manager = application.getMaterialManager()
-
- # Force update lookup tables first
- material_manager.initialize()
-
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
for position, extruder_stack in extruder_stack_dict.items():
if position not in self._machine_info.extruder_info_dict:
continue
@@ -930,18 +966,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
root_material_id = extruder_info.root_material_id
root_material_id = self._old_new_materials.get(root_material_id, root_material_id)
- build_plate_id = global_stack.variant.getId()
-
- # get material diameter of this extruder
- machine_material_diameter = extruder_stack.getCompatibleMaterialDiameter()
- material_node = material_manager.getMaterialNode(global_stack.definition.getId(),
- extruder_stack.variant.getName(),
- build_plate_id,
- machine_material_diameter,
- root_material_id)
-
- if material_node is not None and material_node.getContainer() is not None:
- extruder_stack.material = material_node.getContainer() # type: InstanceContainer
+ material_node = machine_node.variants[extruder_stack.variant.getName()].materials[root_material_id]
+ extruder_stack.material = material_node.container # type: InstanceContainer
def _applyChangesToMachine(self, global_stack, extruder_stack_dict):
# Clear all first
@@ -957,10 +983,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# prepare the quality to select
self._quality_changes_to_apply = None
self._quality_type_to_apply = None
+ self._intent_category_to_apply = None
if self._machine_info.quality_changes_info is not None:
self._quality_changes_to_apply = self._machine_info.quality_changes_info.name
else:
self._quality_type_to_apply = self._machine_info.quality_type
+ self._intent_category_to_apply = self._machine_info.intent_category
# Set enabled/disabled for extruders
for position, extruder_stack in extruder_stack_dict.items():
@@ -971,34 +999,38 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
extruder_stack.setMetaDataEntry("enabled", "True")
extruder_stack.setMetaDataEntry("enabled", str(extruder_info.enabled))
+ # Set metadata fields that are missing from the global stack
+ for key, value in self._machine_info.metadata_dict.items():
+ if key not in global_stack.getMetaData():
+ global_stack.setMetaDataEntry(key, value)
+
def _updateActiveMachine(self, global_stack):
# Actually change the active machine.
machine_manager = Application.getInstance().getMachineManager()
- material_manager = Application.getInstance().getMaterialManager()
- quality_manager = Application.getInstance().getQualityManager()
-
- # Force update the lookup maps first
- material_manager.initialize()
- quality_manager.initialize()
+ container_tree = ContainerTree.getInstance()
machine_manager.setActiveMachine(global_stack.getId())
+ # Set metadata fields that are missing from the global stack
+ for key, value in self._machine_info.metadata_dict.items():
+ if key not in global_stack.getMetaData():
+ global_stack.setMetaDataEntry(key, value)
+
if self._quality_changes_to_apply:
- quality_changes_group_dict = quality_manager.getQualityChangesGroups(global_stack)
- if self._quality_changes_to_apply not in quality_changes_group_dict:
+ quality_changes_group_list = container_tree.getCurrentQualityChangesGroups()
+ quality_changes_group = next((qcg for qcg in quality_changes_group_list if qcg.name == self._quality_changes_to_apply), None)
+ if not quality_changes_group:
Logger.log("e", "Could not find quality_changes [%s]", self._quality_changes_to_apply)
return
- quality_changes_group = quality_changes_group_dict[self._quality_changes_to_apply]
machine_manager.setQualityChangesGroup(quality_changes_group, no_dialog = True)
else:
self._quality_type_to_apply = self._quality_type_to_apply.lower()
- quality_group_dict = quality_manager.getQualityGroups(global_stack)
+ quality_group_dict = container_tree.getCurrentQualityGroups()
if self._quality_type_to_apply in quality_group_dict:
quality_group = quality_group_dict[self._quality_type_to_apply]
else:
Logger.log("i", "Could not find quality type [%s], switch to default", self._quality_type_to_apply)
preferred_quality_type = global_stack.getMetaDataEntry("preferred_quality_type")
- quality_group_dict = quality_manager.getQualityGroups(global_stack)
quality_group = quality_group_dict.get(preferred_quality_type)
if quality_group is None:
Logger.log("e", "Could not get preferred quality type [%s]", preferred_quality_type)
@@ -1006,10 +1038,16 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if quality_group is not None:
machine_manager.setQualityGroup(quality_group, no_dialog = True)
+ # Also apply intent if available
+ available_intent_category_list = IntentManager.getInstance().currentAvailableIntentCategories()
+ if self._intent_category_to_apply is not None and self._intent_category_to_apply in available_intent_category_list:
+ machine_manager.setIntentByCategory(self._intent_category_to_apply)
+
# Notify everything/one that is to notify about changes.
global_stack.containersChanged.emit(global_stack.getTop())
- def _stripFileToId(self, file):
+ @staticmethod
+ def _stripFileToId(file):
mime_type = MimeTypeDatabase.getMimeTypeForFile(file)
file = mime_type.stripExtension(file)
return file.replace("Cura/", "")
@@ -1018,7 +1056,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
return self._container_registry.getContainerForMimeType(MimeTypeDatabase.getMimeType("application/x-ultimaker-material-profile"))
## Get the list of ID's of all containers in a container stack by partially parsing it's serialized data.
- def _getContainerIdListFromSerialized(self, serialized):
+ @staticmethod
+ def _getContainerIdListFromSerialized(serialized):
parser = ConfigParser(interpolation = None, empty_lines_in_values = False)
parser.read_string(serialized)
@@ -1039,12 +1078,20 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
return container_ids
- def _getMachineNameFromSerializedStack(self, serialized):
+ @staticmethod
+ def _getMachineNameFromSerializedStack(serialized):
parser = ConfigParser(interpolation = None, empty_lines_in_values = False)
parser.read_string(serialized)
return parser["general"].get("name", "")
- def _getMaterialLabelFromSerialized(self, serialized):
+ @staticmethod
+ def _getMetaDataDictFromSerializedStack(serialized: str) -> Dict[str, str]:
+ parser = ConfigParser(interpolation = None, empty_lines_in_values = False)
+ parser.read_string(serialized)
+ return dict(parser["metadata"])
+
+ @staticmethod
+ def _getMaterialLabelFromSerialized(serialized):
data = ET.fromstring(serialized)
metadata = data.iterfind("./um:metadata/um:name/um:label", {"um": "http://www.ultimaker.com/material"})
for entry in metadata:
diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py
index 6e1cbb2019..3df7f1f570 100644
--- a/plugins/3MFReader/WorkspaceDialog.py
+++ b/plugins/3MFReader/WorkspaceDialog.py
@@ -41,8 +41,9 @@ class WorkspaceDialog(QObject):
self._num_user_settings = 0
self._active_mode = ""
self._quality_name = ""
- self._num_settings_overriden_by_quality_changes = 0
+ self._num_settings_overridden_by_quality_changes = 0
self._quality_type = ""
+ self._intent_name = ""
self._machine_name = ""
self._machine_type = ""
self._variant_type = ""
@@ -60,6 +61,7 @@ class WorkspaceDialog(QObject):
hasVisibleSettingsFieldChanged = pyqtSignal()
numSettingsOverridenByQualityChangesChanged = pyqtSignal()
qualityTypeChanged = pyqtSignal()
+ intentNameChanged = pyqtSignal()
machineNameChanged = pyqtSignal()
materialLabelsChanged = pyqtSignal()
objectsOnPlateChanged = pyqtSignal()
@@ -151,10 +153,10 @@ class WorkspaceDialog(QObject):
@pyqtProperty(int, notify=numSettingsOverridenByQualityChangesChanged)
def numSettingsOverridenByQualityChanges(self):
- return self._num_settings_overriden_by_quality_changes
+ return self._num_settings_overridden_by_quality_changes
- def setNumSettingsOverridenByQualityChanges(self, num_settings_overriden_by_quality_changes):
- self._num_settings_overriden_by_quality_changes = num_settings_overriden_by_quality_changes
+ def setNumSettingsOverriddenByQualityChanges(self, num_settings_overridden_by_quality_changes):
+ self._num_settings_overridden_by_quality_changes = num_settings_overridden_by_quality_changes
self.numSettingsOverridenByQualityChangesChanged.emit()
@pyqtProperty(str, notify=qualityNameChanged)
@@ -166,6 +168,15 @@ class WorkspaceDialog(QObject):
self._quality_name = quality_name
self.qualityNameChanged.emit()
+ @pyqtProperty(str, notify = intentNameChanged)
+ def intentName(self) -> str:
+ return self._intent_name
+
+ def setIntentName(self, intent_name: str) -> None:
+ if self._intent_name != intent_name:
+ self._intent_name = intent_name
+ self.intentNameChanged.emit()
+
@pyqtProperty(str, notify=activeModeChanged)
def activeMode(self):
return self._active_mode
diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml
index 58d881c915..d0fd3d0846 100644
--- a/plugins/3MFReader/WorkspaceDialog.qml
+++ b/plugins/3MFReader/WorkspaceDialog.qml
@@ -1,10 +1,10 @@
// Copyright (c) 2016 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.1
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
+import QtQuick 2.10
+import QtQuick.Controls 1.4
+import QtQuick.Layouts 1.3
+import QtQuick.Window 2.2
import UM 1.1 as UM
@@ -13,8 +13,8 @@ UM.Dialog
id: base
title: catalog.i18nc("@title:window", "Open Project")
- minimumWidth: 500 * screenScaleFactor
- minimumHeight: 450 * screenScaleFactor
+ minimumWidth: UM.Theme.getSize("popup_dialog").width
+ minimumHeight: UM.Theme.getSize("popup_dialog").height
width: minimumWidth
height: minimumHeight
@@ -24,7 +24,7 @@ UM.Dialog
onClosing: manager.notifyClosed()
onVisibleChanged:
{
- if(visible)
+ if (visible)
{
machineResolveComboBox.currentIndex = 0
qualityChangesResolveComboBox.currentIndex = 0
@@ -55,8 +55,8 @@ UM.Dialog
// See http://stackoverflow.com/questions/7659442/listelement-fields-as-properties
Component.onCompleted:
{
- append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update existing")});
- append({"key": "new", "label": catalog.i18nc("@action:ComboBox option", "Create new")});
+ append({"key": "override", "label": catalog.i18nc("@action:ComboBox Update/override existing profile", "Update existing")});
+ append({"key": "new", "label": catalog.i18nc("@action:ComboBox Save settings in a new profile", "Create new")});
}
}
@@ -223,6 +223,21 @@ UM.Dialog
}
}
Row
+ {
+ width: parent.width
+ height: childrenRect.height
+ Label
+ {
+ text: catalog.i18nc("@action:label", "Intent")
+ width: (parent.width / 3) | 0
+ }
+ Label
+ {
+ text: manager.intentName
+ width: (parent.width / 3) | 0
+ }
+ }
+ Row
{
width: parent.width
height: manager.numUserSettings != 0 ? childrenRect.height : 0
diff --git a/plugins/3MFReader/__init__.py b/plugins/3MFReader/__init__.py
index ce94bbe69c..d68338c35f 100644
--- a/plugins/3MFReader/__init__.py
+++ b/plugins/3MFReader/__init__.py
@@ -12,7 +12,6 @@ except ImportError:
from . import ThreeMFWorkspaceReader
from UM.i18n import i18nCatalog
-from UM.Platform import Platform
catalog = i18nCatalog("cura")
diff --git a/plugins/3MFReader/plugin.json b/plugins/3MFReader/plugin.json
index 5af21a7033..e366a5da72 100644
--- a/plugins/3MFReader/plugin.json
+++ b/plugins/3MFReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for reading 3MF files.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/3MFWriter/plugin.json b/plugins/3MFWriter/plugin.json
index 3820ebd2e7..5c72072447 100644
--- a/plugins/3MFWriter/plugin.json
+++ b/plugins/3MFWriter/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for writing 3MF files.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/AMFReader/AMFReader.py b/plugins/AMFReader/AMFReader.py
new file mode 100644
index 0000000000..6c5ee91e87
--- /dev/null
+++ b/plugins/AMFReader/AMFReader.py
@@ -0,0 +1,173 @@
+# Copyright (c) 2019 fieldOfView, Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+# This AMF parser is based on the AMF parser in legacy cura:
+# https://github.com/daid/LegacyCura/blob/ad7641e059048c7dcb25da1f47c0a7e95e7f4f7c/Cura/util/meshLoaders/amf.py
+from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
+from cura.CuraApplication import CuraApplication
+from UM.Logger import Logger
+
+from UM.Mesh.MeshData import MeshData, calculateNormalsFromIndexedVertices
+from UM.Mesh.MeshReader import MeshReader
+
+from cura.Scene.CuraSceneNode import CuraSceneNode
+from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
+from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
+from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
+from UM.Scene.GroupDecorator import GroupDecorator
+
+import numpy
+import trimesh
+import os.path
+import zipfile
+
+MYPY = False
+try:
+ if not MYPY:
+ import xml.etree.cElementTree as ET
+except ImportError:
+ import xml.etree.ElementTree as ET
+
+from typing import Dict
+
+
+class AMFReader(MeshReader):
+ def __init__(self) -> None:
+ super().__init__()
+ self._supported_extensions = [".amf"]
+ self._namespaces = {} # type: Dict[str, str]
+
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "application/x-amf",
+ comment = "AMF",
+ suffixes = ["amf"]
+ )
+ )
+
+ # Main entry point
+ # Reads the file, returns a SceneNode (possibly with nested ones), or None
+ def _read(self, file_name):
+ base_name = os.path.basename(file_name)
+ try:
+ zipped_file = zipfile.ZipFile(file_name)
+ xml_document = zipped_file.read(zipped_file.namelist()[0])
+ zipped_file.close()
+ except zipfile.BadZipfile:
+ raw_file = open(file_name, "r")
+ xml_document = raw_file.read()
+ raw_file.close()
+
+ try:
+ amf_document = ET.fromstring(xml_document)
+ except ET.ParseError:
+ Logger.log("e", "Could not parse XML in file %s" % base_name)
+ return None
+
+ if "unit" in amf_document.attrib:
+ unit = amf_document.attrib["unit"].lower()
+ else:
+ unit = "millimeter"
+ if unit == "millimeter":
+ scale = 1.0
+ elif unit == "meter":
+ scale = 1000.0
+ elif unit == "inch":
+ scale = 25.4
+ elif unit == "feet":
+ scale = 304.8
+ elif unit == "micron":
+ scale = 0.001
+ else:
+ Logger.log("w", "Unknown unit in amf: %s. Using mm instead." % unit)
+ scale = 1.0
+
+ nodes = []
+ for amf_object in amf_document.iter("object"):
+ for amf_mesh in amf_object.iter("mesh"):
+ amf_mesh_vertices = []
+ for vertices in amf_mesh.iter("vertices"):
+ for vertex in vertices.iter("vertex"):
+ for coordinates in vertex.iter("coordinates"):
+ v = [0.0, 0.0, 0.0]
+ for t in coordinates:
+ if t.tag == "x":
+ v[0] = float(t.text) * scale
+ elif t.tag == "y":
+ v[2] = -float(t.text) * scale
+ elif t.tag == "z":
+ v[1] = float(t.text) * scale
+ amf_mesh_vertices.append(v)
+ if not amf_mesh_vertices:
+ continue
+
+ indices = []
+ for volume in amf_mesh.iter("volume"):
+ for triangle in volume.iter("triangle"):
+ f = [0, 0, 0]
+ for t in triangle:
+ if t.tag == "v1":
+ f[0] = int(t.text)
+ elif t.tag == "v2":
+ f[1] = int(t.text)
+ elif t.tag == "v3":
+ f[2] = int(t.text)
+ indices.append(f)
+
+ mesh = trimesh.base.Trimesh(vertices = numpy.array(amf_mesh_vertices, dtype = numpy.float32), faces = numpy.array(indices, dtype = numpy.int32))
+ mesh.merge_vertices()
+ mesh.remove_unreferenced_vertices()
+ mesh.fix_normals()
+ mesh_data = self._toMeshData(mesh)
+
+ new_node = CuraSceneNode()
+ new_node.setSelectable(True)
+ new_node.setMeshData(mesh_data)
+ new_node.setName(base_name if len(nodes) == 0 else "%s %d" % (base_name, len(nodes)))
+ new_node.addDecorator(BuildPlateDecorator(CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate))
+ new_node.addDecorator(SliceableObjectDecorator())
+
+ nodes.append(new_node)
+
+ if not nodes:
+ Logger.log("e", "No meshes in file %s" % base_name)
+ return None
+
+ if len(nodes) == 1:
+ return nodes[0]
+
+ # Add all scenenodes to a group so they stay together
+ group_node = CuraSceneNode()
+ group_node.addDecorator(GroupDecorator())
+ group_node.addDecorator(ConvexHullDecorator())
+ group_node.addDecorator(BuildPlateDecorator(CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate))
+
+ for node in nodes:
+ node.setParent(group_node)
+
+ return group_node
+
+ def _toMeshData(self, tri_node: trimesh.base.Trimesh) -> MeshData:
+ tri_faces = tri_node.faces
+ tri_vertices = tri_node.vertices
+
+ indices = []
+ vertices = []
+
+ index_count = 0
+ face_count = 0
+ for tri_face in tri_faces:
+ face = []
+ for tri_index in tri_face:
+ vertices.append(tri_vertices[tri_index])
+ face.append(index_count)
+ index_count += 1
+ indices.append(face)
+ face_count += 1
+
+ vertices = numpy.asarray(vertices, dtype = numpy.float32)
+ indices = numpy.asarray(indices, dtype = numpy.int32)
+ normals = calculateNormalsFromIndexedVertices(vertices, indices, face_count)
+
+ mesh_data = MeshData(vertices = vertices, indices = indices, normals = normals)
+ return mesh_data
diff --git a/plugins/AMFReader/__init__.py b/plugins/AMFReader/__init__.py
new file mode 100644
index 0000000000..c974a92d11
--- /dev/null
+++ b/plugins/AMFReader/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2019 fieldOfView
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from . import AMFReader
+
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("uranium")
+
+
+def getMetaData():
+ return {
+ "mesh_reader": [
+ {
+ "extension": "amf",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "AMF File")
+ }
+ ]
+ }
+
+def register(app):
+ return {"mesh_reader": AMFReader.AMFReader()}
diff --git a/plugins/AMFReader/plugin.json b/plugins/AMFReader/plugin.json
new file mode 100644
index 0000000000..5e5b0f211b
--- /dev/null
+++ b/plugins/AMFReader/plugin.json
@@ -0,0 +1,7 @@
+{
+ "name": "AMF Reader",
+ "author": "fieldOfView",
+ "version": "1.0.0",
+ "description": "Provides support for reading AMF files.",
+ "api": "7.0.0"
+}
diff --git a/plugins/ChangeLogPlugin/ChangeLog.py b/plugins/ChangeLogPlugin/ChangeLog.py
deleted file mode 100644
index eeec5edf9b..0000000000
--- a/plugins/ChangeLogPlugin/ChangeLog.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from UM.i18n import i18nCatalog
-from UM.Extension import Extension
-from UM.Application import Application
-from UM.PluginRegistry import PluginRegistry
-from UM.Version import Version
-
-from PyQt5.QtCore import pyqtSlot, QObject
-
-import os.path
-import collections
-
-catalog = i18nCatalog("cura")
-
-class ChangeLog(Extension, QObject,):
- def __init__(self, parent = None):
- QObject.__init__(self, parent)
- Extension.__init__(self)
- self._changelog_window = None
- self._changelog_context = None
- version_string = Application.getInstance().getVersion()
- if version_string is not "master":
- self._current_app_version = Version(version_string)
- else:
- self._current_app_version = None
-
- self._change_logs = None
- Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
- Application.getInstance().getPreferences().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium
- self.setMenuName(catalog.i18nc("@item:inmenu", "Changelog"))
- self.addMenuItem(catalog.i18nc("@item:inmenu", "Show Changelog"), self.showChangelog)
-
- def getChangeLogs(self):
- if not self._change_logs:
- self.loadChangeLogs()
- return self._change_logs
-
- @pyqtSlot(result = str)
- def getChangeLogString(self):
- logs = self.getChangeLogs()
- result = ""
- for version in logs:
- result += "
" + str(version) + "
"
- result += ""
- for change in logs[version]:
- if str(change) != "":
- result += "" + str(change) + " "
- for line in logs[version][change]:
- result += str(line) + " "
- result += " "
-
- pass
- return result
-
- def loadChangeLogs(self):
- self._change_logs = collections.OrderedDict()
- with open(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.txt"), "r", encoding = "utf-8") as f:
- open_version = None
- open_header = "" # Initialise to an empty header in case there is no "*" in the first line of the changelog
- for line in f:
- line = line.replace("\n","")
- if "[" in line and "]" in line:
- line = line.replace("[","")
- line = line.replace("]","")
- open_version = Version(line)
- open_header = ""
- self._change_logs[open_version] = collections.OrderedDict()
- elif line.startswith("*"):
- open_header = line.replace("*","")
- self._change_logs[open_version][open_header] = []
- elif line != "":
- if open_header not in self._change_logs[open_version]:
- self._change_logs[open_version][open_header] = []
- self._change_logs[open_version][open_header].append(line)
-
- def _onEngineCreated(self):
- if not self._current_app_version:
- return #We're on dev branch.
-
- if Application.getInstance().getPreferences().getValue("general/latest_version_changelog_shown") == "master":
- latest_version_shown = Version("0.0.0")
- else:
- latest_version_shown = Version(Application.getInstance().getPreferences().getValue("general/latest_version_changelog_shown"))
-
- Application.getInstance().getPreferences().setValue("general/latest_version_changelog_shown", Application.getInstance().getVersion())
-
- # Do not show the changelog when there is no global container stack
- # This implies we are running Cura for the first time.
- if not Application.getInstance().getGlobalContainerStack():
- return
-
- if self._current_app_version > latest_version_shown:
- self.showChangelog()
-
- def showChangelog(self):
- if not self._changelog_window:
- self.createChangelogWindow()
-
- self._changelog_window.show()
-
- def hideChangelog(self):
- if self._changelog_window:
- self._changelog_window.hide()
-
- def createChangelogWindow(self):
- path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml")
- self._changelog_window = Application.getInstance().createQmlComponent(path, {"manager": self})
diff --git a/plugins/ChangeLogPlugin/ChangeLog.qml b/plugins/ChangeLogPlugin/ChangeLog.qml
deleted file mode 100644
index 512687f15a..0000000000
--- a/plugins/ChangeLogPlugin/ChangeLog.qml
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2015 Ultimaker B.V.
-// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.1
-import QtQuick.Controls 1.3
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
-
-import UM 1.1 as UM
-
-UM.Dialog
-{
- id: base
- minimumWidth: (UM.Theme.getSize("modal_window_minimum").width * 0.75) | 0
- minimumHeight: (UM.Theme.getSize("modal_window_minimum").height * 0.75) | 0
- width: minimumWidth
- height: minimumHeight
- title: catalog.i18nc("@label", "Changelog")
-
- TextArea
- {
- anchors.fill: parent
- text: manager.getChangeLogString()
- readOnly: true;
- textFormat: TextEdit.RichText
- }
-
- rightButtons: [
- Button
- {
- UM.I18nCatalog
- {
- id: catalog
- name: "cura"
- }
-
- text: catalog.i18nc("@action:button", "Close")
- onClicked: base.hide()
- }
- ]
-}
diff --git a/plugins/ChangeLogPlugin/__init__.py b/plugins/ChangeLogPlugin/__init__.py
deleted file mode 100644
index a5452b60c8..0000000000
--- a/plugins/ChangeLogPlugin/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from . import ChangeLog
-
-
-def getMetaData():
- return {}
-
-def register(app):
- return {"extension": ChangeLog.ChangeLog()}
diff --git a/plugins/ChangeLogPlugin/plugin.json b/plugins/ChangeLogPlugin/plugin.json
deleted file mode 100644
index 92041d1543..0000000000
--- a/plugins/ChangeLogPlugin/plugin.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "Changelog",
- "author": "Ultimaker B.V.",
- "version": "1.0.1",
- "description": "Shows changes since latest checked version.",
- "api": "6.0",
- "i18n-catalog": "cura"
-}
diff --git a/plugins/CuraDrive/plugin.json b/plugins/CuraDrive/plugin.json
index d1cab39ca5..9b9b3e2c15 100644
--- a/plugins/CuraDrive/plugin.json
+++ b/plugins/CuraDrive/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"description": "Backup and restore your configuration.",
"version": "1.2.0",
- "api": 6,
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py
index 49e242d851..d8349ccc29 100644
--- a/plugins/CuraDrive/src/DriveApiService.py
+++ b/plugins/CuraDrive/src/DriveApiService.py
@@ -45,7 +45,7 @@ class DriveApiService:
"Authorization": "Bearer {}".format(access_token)
})
except requests.exceptions.ConnectionError:
- Logger.log("w", "Unable to connect with the server.")
+ Logger.logException("w", "Unable to connect with the server.")
return []
# HTTP status 300s mean redirection. 400s and 500s are errors.
@@ -98,7 +98,12 @@ class DriveApiService:
# If there is no download URL, we can't restore the backup.
return self._emitRestoreError()
- download_package = requests.get(download_url, stream = True)
+ try:
+ download_package = requests.get(download_url, stream = True)
+ except requests.exceptions.ConnectionError:
+ Logger.logException("e", "Unable to connect with the server")
+ return self._emitRestoreError()
+
if download_package.status_code >= 300:
# Something went wrong when attempting to download the backup.
Logger.log("w", "Could not download backup from url %s: %s", download_url, download_package.text)
@@ -142,9 +147,14 @@ class DriveApiService:
Logger.log("w", "Could not get access token.")
return False
- delete_backup = requests.delete("{}/{}".format(self.BACKUP_URL, backup_id), headers = {
- "Authorization": "Bearer {}".format(access_token)
- })
+ try:
+ delete_backup = requests.delete("{}/{}".format(self.BACKUP_URL, backup_id), headers = {
+ "Authorization": "Bearer {}".format(access_token)
+ })
+ except requests.exceptions.ConnectionError:
+ Logger.logException("e", "Unable to connect with the server")
+ return False
+
if delete_backup.status_code >= 300:
Logger.log("w", "Could not delete backup: %s", delete_backup.text)
return False
@@ -159,15 +169,19 @@ class DriveApiService:
if not access_token:
Logger.log("w", "Could not get access token.")
return None
-
- backup_upload_request = requests.put(self.BACKUP_URL, json = {
- "data": {
- "backup_size": backup_size,
- "metadata": backup_metadata
- }
- }, headers = {
- "Authorization": "Bearer {}".format(access_token)
- })
+ try:
+ backup_upload_request = requests.put(
+ self.BACKUP_URL,
+ json = {"data": {"backup_size": backup_size,
+ "metadata": backup_metadata
+ }
+ },
+ headers = {
+ "Authorization": "Bearer {}".format(access_token)
+ })
+ except requests.exceptions.ConnectionError:
+ Logger.logException("e", "Unable to connect with the server")
+ return None
# Any status code of 300 or above indicates an error.
if backup_upload_request.status_code >= 300:
diff --git a/plugins/CuraDrive/src/qml/main.qml b/plugins/CuraDrive/src/qml/main.qml
index 48bf3b6ea4..796a31e1d3 100644
--- a/plugins/CuraDrive/src/qml/main.qml
+++ b/plugins/CuraDrive/src/qml/main.qml
@@ -18,6 +18,7 @@ Window
minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height)
maximumWidth: Math.round(minimumWidth * 1.2)
maximumHeight: Math.round(minimumHeight * 1.2)
+ modality: Qt.ApplicationModal
width: minimumWidth
height: minimumHeight
color: UM.Theme.getColor("main_background")
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py
index ceba5f3006..1437153f32 100755
--- a/plugins/CuraEngineBackend/CuraEngineBackend.py
+++ b/plugins/CuraEngineBackend/CuraEngineBackend.py
@@ -10,20 +10,17 @@ from time import time
from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING
from UM.Backend.Backend import Backend, BackendState
-from UM.Scene.Camera import Camera
from UM.Scene.SceneNode import SceneNode
from UM.Signal import Signal
from UM.Logger import Logger
from UM.Message import Message
from UM.PluginRegistry import PluginRegistry
-from UM.Resources import Resources
from UM.Platform import Platform
from UM.Qt.Duration import DurationFormat
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Settings.Interfaces import DefinitionContainerInterface
from UM.Settings.SettingInstance import SettingInstance #For typing.
from UM.Tool import Tool #For typing.
-from UM.Mesh.MeshData import MeshData #For typing.
from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager
@@ -210,7 +207,7 @@ class CuraEngineBackend(QObject, Backend):
self._createSocket()
if self._process_layers_job is not None: # We were processing layers. Stop that, the layers are going to change soon.
- Logger.log("d", "Aborting process layers job...")
+ Logger.log("i", "Aborting process layers job...")
self._process_layers_job.abort()
self._process_layers_job = None
@@ -225,7 +222,7 @@ class CuraEngineBackend(QObject, Backend):
## Perform a slice of the scene.
def slice(self) -> None:
- Logger.log("d", "Starting to slice...")
+ Logger.log("i", "Starting to slice...")
self._slice_start_time = time()
if not self._build_plates_to_be_sliced:
self.processingProgress.emit(1.0)
@@ -372,7 +369,7 @@ class CuraEngineBackend(QObject, Backend):
elif job.getResult() == StartJobResult.ObjectSettingError:
errors = {}
- for node in DepthFirstIterator(self._application.getController().getScene().getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(self._application.getController().getScene().getRoot()):
stack = node.callDecoration("getStack")
if not stack:
continue
@@ -403,7 +400,7 @@ class CuraEngineBackend(QObject, Backend):
self.setState(BackendState.NotStarted)
if job.getResult() == StartJobResult.ObjectsWithDisabledExtruder:
- self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because there are objects associated with disabled Extruder %s." % job.getMessage()),
+ self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because there are objects associated with disabled Extruder %s.") % job.getMessage(),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.setState(BackendState.Error)
@@ -441,7 +438,7 @@ class CuraEngineBackend(QObject, Backend):
if not self._application.getPreferences().getValue("general/auto_slice"):
enable_timer = False
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(self._scene.getRoot()):
if node.callDecoration("isBlockSlicing"):
enable_timer = False
self.setState(BackendState.Disabled)
@@ -463,7 +460,7 @@ class CuraEngineBackend(QObject, Backend):
## Return a dict with number of objects per build plate
def _numObjectsPerBuildPlate(self) -> Dict[int, int]:
num_objects = defaultdict(int) #type: Dict[int, int]
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(self._scene.getRoot()):
# Only count sliceable objects
if node.callDecoration("isSliceable"):
build_plate_number = node.callDecoration("getBuildPlateNumber")
@@ -520,9 +517,6 @@ class CuraEngineBackend(QObject, Backend):
self._build_plates_to_be_sliced.append(build_plate_number)
self.printDurationMessage.emit(source_build_plate_number, {}, [])
self.processingProgress.emit(0.0)
- self.setState(BackendState.NotStarted)
- # if not self._use_timer:
- # With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData(build_plate_changed)
self._invokeSlice()
@@ -549,15 +543,25 @@ class CuraEngineBackend(QObject, Backend):
if error.getErrorCode() == Arcus.ErrorCode.BindFailedError and self._start_slice_job is not None:
self._start_slice_job.setIsCancelled(False)
+ # Check if there's any slicable object in the scene.
+ def hasSlicableObject(self) -> bool:
+ has_slicable = False
+ for node in DepthFirstIterator(self._scene.getRoot()):
+ if node.callDecoration("isSliceable"):
+ has_slicable = True
+ break
+ return has_slicable
+
## Remove old layer data (if any)
def _clearLayerData(self, build_plate_numbers: Set = None) -> None:
# Clear out any old gcode
self._scene.gcode_dict = {} # type: ignore
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(self._scene.getRoot()):
if node.callDecoration("getLayerData"):
if not build_plate_numbers or node.callDecoration("getBuildPlateNumber") in build_plate_numbers:
- node.getParent().removeChild(node)
+ # We can asume that all nodes have a parent as we're looping through the scene (and filter out root)
+ cast(SceneNode, node.getParent()).removeChild(node)
def markSliceAll(self) -> None:
for build_plate_number in range(self._application.getMultiBuildPlateModel().maxBuildPlate + 1):
@@ -566,10 +570,14 @@ class CuraEngineBackend(QObject, Backend):
## Convenient function: mark everything to slice, emit state and clear layer data
def needsSlicing(self) -> None:
+ # CURA-6604: If there's no slicable object, do not (try to) trigger slice, which will clear all the current
+ # gcode. This can break Gcode file loading if it tries to remove it afterwards.
+ if not self.hasSlicableObject():
+ return
+ self.determineAutoSlicing()
self.stopSlicing()
self.markSliceAll()
self.processingProgress.emit(0.0)
- self.setState(BackendState.NotStarted)
if not self._use_timer:
# With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData()
@@ -637,7 +645,10 @@ class CuraEngineBackend(QObject, Backend):
self.setState(BackendState.Done)
self.processingProgress.emit(1.0)
- gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate] #type: ignore #Because we generate this attribute dynamically.
+ try:
+ gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate] #type: ignore #Because we generate this attribute dynamically.
+ except KeyError: # Can occur if the g-code has been cleared while a slice message is still arriving from the other end.
+ gcode_list = []
for index, line in enumerate(gcode_list):
replaced = line.replace("{print_time}", str(self._application.getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601)))
replaced = replaced.replace("{filament_amount}", str(self._application.getPrintInformation().materialLengths))
@@ -676,14 +687,20 @@ class CuraEngineBackend(QObject, Backend):
#
# \param message The protobuf message containing g-code, encoded as UTF-8.
def _onGCodeLayerMessage(self, message: Arcus.PythonMessage) -> None:
- self._scene.gcode_dict[self._start_slice_job_build_plate].append(message.data.decode("utf-8", "replace")) #type: ignore #Because we generate this attribute dynamically.
+ try:
+ self._scene.gcode_dict[self._start_slice_job_build_plate].append(message.data.decode("utf-8", "replace")) #type: ignore #Because we generate this attribute dynamically.
+ except KeyError: # Can occur if the g-code has been cleared while a slice message is still arriving from the other end.
+ pass # Throw the message away.
## Called when a g-code prefix message is received from the engine.
#
# \param message The protobuf message containing the g-code prefix,
# encoded as UTF-8.
def _onGCodePrefixMessage(self, message: Arcus.PythonMessage) -> None:
- self._scene.gcode_dict[self._start_slice_job_build_plate].insert(0, message.data.decode("utf-8", "replace")) #type: ignore #Because we generate this attribute dynamically.
+ try:
+ self._scene.gcode_dict[self._start_slice_job_build_plate].insert(0, message.data.decode("utf-8", "replace")) #type: ignore #Because we generate this attribute dynamically.
+ except KeyError: # Can occur if the g-code has been cleared while a slice message is still arriving from the other end.
+ pass # Throw the message away.
## Creates a new socket connection.
def _createSocket(self, protocol_file: str = None) -> None:
@@ -738,6 +755,7 @@ class CuraEngineBackend(QObject, Backend):
"support_interface": message.time_support_interface,
"support": message.time_support,
"skirt": message.time_skirt,
+ "prime_tower": message.time_prime_tower,
"travel": message.time_travel,
"retract": message.time_retract,
"none": message.time_none
@@ -816,9 +834,8 @@ class CuraEngineBackend(QObject, Backend):
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
self._global_container_stack.containersChanged.disconnect(self._onChanged)
- extruders = list(self._global_container_stack.extruders.values())
- for extruder in extruders:
+ for extruder in self._global_container_stack.extruderList:
extruder.propertyChanged.disconnect(self._onSettingChanged)
extruder.containersChanged.disconnect(self._onChanged)
@@ -827,8 +844,8 @@ class CuraEngineBackend(QObject, Backend):
if self._global_container_stack:
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
self._global_container_stack.containersChanged.connect(self._onChanged)
- extruders = list(self._global_container_stack.extruders.values())
- for extruder in extruders:
+
+ for extruder in self._global_container_stack.extruderList:
extruder.propertyChanged.connect(self._onSettingChanged)
extruder.containersChanged.connect(self._onChanged)
self._onChanged()
diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
index 3cc23130ea..32d60eb68b 100644
--- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
+++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
@@ -1,4 +1,4 @@
-#Copyright (c) 2017 Ultimaker B.V.
+#Copyright (c) 2019 Ultimaker B.V.
#Cura is released under the terms of the LGPLv3 or higher.
import gc
@@ -24,7 +24,7 @@ from cura import LayerPolygon
import numpy
from time import time
-from cura.Settings.ExtrudersModel import ExtrudersModel
+from cura.Machines.Models.ExtrudersModel import ExtrudersModel
catalog = i18nCatalog("cura")
@@ -136,23 +136,23 @@ class ProcessSlicedLayersJob(Job):
extruder = polygon.extruder
- line_types = numpy.fromstring(polygon.line_type, dtype="u1") # Convert bytearray to numpy array
+ line_types = numpy.fromstring(polygon.line_type, dtype = "u1") # Convert bytearray to numpy array
line_types = line_types.reshape((-1,1))
- points = numpy.fromstring(polygon.points, dtype="f4") # Convert bytearray to numpy array
+ points = numpy.fromstring(polygon.points, dtype = "f4") # Convert bytearray to numpy array
if polygon.point_type == 0: # Point2D
points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly.
else: # Point3D
points = points.reshape((-1,3))
- line_widths = numpy.fromstring(polygon.line_width, dtype="f4") # Convert bytearray to numpy array
+ line_widths = numpy.fromstring(polygon.line_width, dtype = "f4") # Convert bytearray to numpy array
line_widths = line_widths.reshape((-1,1)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly.
- line_thicknesses = numpy.fromstring(polygon.line_thickness, dtype="f4") # Convert bytearray to numpy array
+ line_thicknesses = numpy.fromstring(polygon.line_thickness, dtype = "f4") # Convert bytearray to numpy array
line_thicknesses = line_thicknesses.reshape((-1,1)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly.
- line_feedrates = numpy.fromstring(polygon.line_feedrate, dtype="f4") # Convert bytearray to numpy array
+ line_feedrates = numpy.fromstring(polygon.line_feedrate, dtype = "f4") # Convert bytearray to numpy array
line_feedrates = line_feedrates.reshape((-1,1)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly.
# Create a new 3D-array, copy the 2D points over and insert the right height.
@@ -194,7 +194,7 @@ class ProcessSlicedLayersJob(Job):
manager = ExtruderManager.getInstance()
extruders = manager.getActiveExtruderStacks()
if extruders:
- material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32)
+ material_color_map = numpy.zeros((len(extruders), 4), dtype = numpy.float32)
for extruder in extruders:
position = int(extruder.getMetaDataEntry("position", default = "0"))
try:
@@ -206,8 +206,8 @@ class ProcessSlicedLayersJob(Job):
material_color_map[position, :] = color
else:
# Single extruder via global stack.
- material_color_map = numpy.zeros((1, 4), dtype=numpy.float32)
- color_code = global_container_stack.material.getMetaDataEntry("color_code", default="#e0e000")
+ material_color_map = numpy.zeros((1, 4), dtype = numpy.float32)
+ color_code = global_container_stack.material.getMetaDataEntry("color_code", default = "#e0e000")
color = colorCodeToRGBA(color_code)
material_color_map[0, :] = color
diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py
index ef97364118..43d54d8b12 100644
--- a/plugins/CuraEngineBackend/StartSliceJob.py
+++ b/plugins/CuraEngineBackend/StartSliceJob.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import numpy
@@ -11,6 +11,7 @@ import Arcus #For typing.
from UM.Job import Job
from UM.Logger import Logger
+from UM.Scene.SceneNode import SceneNode
from UM.Settings.ContainerStack import ContainerStack #For typing.
from UM.Settings.SettingRelation import SettingRelation #For typing.
@@ -71,7 +72,7 @@ class GcodeStartEndFormatter(Formatter):
value = default_value_str
# "-1" is global stack, and if the setting value exists in the global stack, use it as the fallback value.
if key in kwargs["-1"]:
- value = kwargs["-1"]
+ value = kwargs["-1"][key]
if str(extruder_nr) in kwargs and key in kwargs[str(extruder_nr)]:
value = kwargs[str(extruder_nr)][key]
@@ -105,9 +106,14 @@ class StartSliceJob(Job):
if stack is None:
return False
+ # if there are no per-object settings we don't need to check the other settings here
+ stack_top = stack.getTop()
+ if stack_top is None or not stack_top.getAllKeys():
+ return False
+
for key in stack.getAllKeys():
validation_state = stack.getProperty(key, "validationState")
- if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
+ if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError, ValidatorState.Invalid):
Logger.log("w", "Setting %s is not valid, but %s. Aborting slicing.", key, validation_state)
return True
Job.yieldThread()
@@ -133,6 +139,14 @@ class StartSliceJob(Job):
self.setResult(StartJobResult.BuildPlateError)
return
+ # Wait for error checker to be done.
+ while CuraApplication.getInstance().getMachineErrorChecker().needToWaitForResult:
+ time.sleep(0.1)
+
+ if CuraApplication.getInstance().getMachineErrorChecker().hasError:
+ self.setResult(StartJobResult.SettingError)
+ return
+
# Don't slice if the buildplate or the nozzle type is incompatible with the materials
if not CuraApplication.getInstance().getMachineManager().variantBuildplateCompatible and \
not CuraApplication.getInstance().getMachineManager().variantBuildplateUsable:
@@ -150,7 +164,7 @@ class StartSliceJob(Job):
# Don't slice if there is a per object setting with an error value.
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(self._scene.getRoot()):
if not isinstance(node, CuraSceneNode) or not node.isSelectable():
continue
@@ -160,15 +174,16 @@ class StartSliceJob(Job):
with self._scene.getSceneLock():
# Remove old layer data.
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in DepthFirstIterator(self._scene.getRoot()):
if node.callDecoration("getLayerData") and node.callDecoration("getBuildPlateNumber") == self._build_plate_number:
- node.getParent().removeChild(node)
+ # Singe we walk through all nodes in the scene, they always have a parent.
+ cast(SceneNode, node.getParent()).removeChild(node)
break
# Get the objects in their groups to print.
object_groups = []
if stack.getProperty("print_sequence", "value") == "one_at_a_time":
- for node in OneAtATimeIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for node in OneAtATimeIterator(self._scene.getRoot()):
temp_list = []
# Node can't be printed, so don't bother sending it.
@@ -183,7 +198,8 @@ class StartSliceJob(Job):
children = node.getAllChildren()
children.append(node)
for child_node in children:
- if child_node.getMeshData() and child_node.getMeshData().getVertices() is not None:
+ mesh_data = child_node.getMeshData()
+ if mesh_data and mesh_data.getVertices() is not None:
temp_list.append(child_node)
if temp_list:
@@ -194,12 +210,10 @@ class StartSliceJob(Job):
else:
temp_list = []
has_printing_mesh = False
- for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
- if node.callDecoration("isSliceable") and node.getMeshData() and node.getMeshData().getVertices() is not None:
- per_object_stack = node.callDecoration("getStack")
- is_non_printing_mesh = False
- if per_object_stack:
- is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS)
+ for node in DepthFirstIterator(self._scene.getRoot()):
+ mesh_data = node.getMeshData()
+ if node.callDecoration("isSliceable") and mesh_data and mesh_data.getVertices() is not None:
+ is_non_printing_mesh = bool(node.callDecoration("isNonPrintingMesh"))
# Find a reason not to add the node
if node.callDecoration("getBuildPlateNumber") != self._build_plate_number:
@@ -213,7 +227,7 @@ class StartSliceJob(Job):
Job.yieldThread()
- #If the list doesn't have any model with suitable settings then clean the list
+ # If the list doesn't have any model with suitable settings then clean the list
# otherwise CuraEngine will crash
if not has_printing_mesh:
temp_list.clear()
@@ -259,18 +273,19 @@ class StartSliceJob(Job):
self._buildGlobalInheritsStackMessage(stack)
# Build messages for extruder stacks
- # Send the extruder settings in the order of extruder positions. Somehow, if you send e.g. extruder 3 first,
- # then CuraEngine can slice with the wrong settings. This I think should be fixed in CuraEngine as well.
- extruder_stack_list = sorted(list(global_stack.extruders.items()), key = lambda item: int(item[0]))
- for _, extruder_stack in extruder_stack_list:
+ for extruder_stack in global_stack.extruderList:
self._buildExtruderMessage(extruder_stack)
for group in filtered_object_groups:
group_message = self._slice_message.addRepeatedMessage("object_lists")
- if group[0].getParent() is not None and group[0].getParent().callDecoration("isGroup"):
- self._handlePerObjectSettings(group[0].getParent(), group_message)
+ parent = group[0].getParent()
+ if parent is not None and parent.callDecoration("isGroup"):
+ self._handlePerObjectSettings(cast(CuraSceneNode, parent), group_message)
+
for object in group:
mesh_data = object.getMeshData()
+ if mesh_data is None:
+ continue
rot_scale = object.getWorldTransformation().getTransposed().getData()[0:3, 0:3]
translate = object.getWorldTransformation().getData()[:3, 3]
@@ -294,7 +309,7 @@ class StartSliceJob(Job):
obj.vertices = flat_verts
- self._handlePerObjectSettings(object, obj)
+ self._handlePerObjectSettings(cast(CuraSceneNode, object), obj)
Job.yieldThread()
@@ -337,25 +352,29 @@ class StartSliceJob(Job):
return result
+ def _cacheAllExtruderSettings(self):
+ global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack())
+
+ # NB: keys must be strings for the string formatter
+ self._all_extruders_settings = {
+ "-1": self._buildReplacementTokens(global_stack)
+ }
+ for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
+ extruder_nr = extruder_stack.getProperty("extruder_nr", "value")
+ self._all_extruders_settings[str(extruder_nr)] = self._buildReplacementTokens(extruder_stack)
+
## Replace setting tokens in a piece of g-code.
# \param value A piece of g-code to replace tokens in.
# \param default_extruder_nr Stack nr to use when no stack nr is specified, defaults to the global stack
def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1) -> str:
if not self._all_extruders_settings:
- global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack())
-
- # NB: keys must be strings for the string formatter
- self._all_extruders_settings = {
- "-1": self._buildReplacementTokens(global_stack)
- }
-
- for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
- extruder_nr = extruder_stack.getProperty("extruder_nr", "value")
- self._all_extruders_settings[str(extruder_nr)] = self._buildReplacementTokens(extruder_stack)
+ self._cacheAllExtruderSettings()
try:
# any setting can be used as a token
fmt = GcodeStartEndFormatter(default_extruder_nr = default_extruder_nr)
+ if self._all_extruders_settings is None:
+ return ""
settings = self._all_extruders_settings.copy()
settings["default_extruder_nr"] = default_extruder_nr
return str(fmt.format(value, **settings))
@@ -367,8 +386,14 @@ class StartSliceJob(Job):
def _buildExtruderMessage(self, stack: ContainerStack) -> None:
message = self._slice_message.addRepeatedMessage("extruders")
message.id = int(stack.getMetaDataEntry("position"))
+ if not self._all_extruders_settings:
+ self._cacheAllExtruderSettings()
- settings = self._buildReplacementTokens(stack)
+ if self._all_extruders_settings is None:
+ return
+
+ extruder_nr = stack.getProperty("extruder_nr", "value")
+ settings = self._all_extruders_settings[str(extruder_nr)].copy()
# Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
settings["material_guid"] = stack.material.getMetaDataEntry("GUID", "")
@@ -392,7 +417,13 @@ class StartSliceJob(Job):
# The settings are taken from the global stack. This does not include any
# per-extruder settings or per-object settings.
def _buildGlobalSettingsMessage(self, stack: ContainerStack) -> None:
- settings = self._buildReplacementTokens(stack)
+ if not self._all_extruders_settings:
+ self._cacheAllExtruderSettings()
+
+ if self._all_extruders_settings is None:
+ return
+
+ settings = self._all_extruders_settings["-1"].copy()
# Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
start_gcode = settings["machine_start_gcode"]
diff --git a/plugins/CuraEngineBackend/plugin.json b/plugins/CuraEngineBackend/plugin.json
index 28f0e294e7..5482e3699e 100644
--- a/plugins/CuraEngineBackend/plugin.json
+++ b/plugins/CuraEngineBackend/plugin.json
@@ -2,7 +2,7 @@
"name": "CuraEngine Backend",
"author": "Ultimaker B.V.",
"description": "Provides the link to the CuraEngine slicing backend.",
- "api": "6.0",
+ "api": "7.0",
"version": "1.0.1",
"i18n-catalog": "cura"
}
diff --git a/plugins/CuraProfileReader/CuraProfileReader.py b/plugins/CuraProfileReader/CuraProfileReader.py
index 11e58dac6d..d4e5d393b2 100644
--- a/plugins/CuraProfileReader/CuraProfileReader.py
+++ b/plugins/CuraProfileReader/CuraProfileReader.py
@@ -1,11 +1,14 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import configparser
-from UM.PluginRegistry import PluginRegistry
+import configparser
+from typing import List, Optional, Tuple
+
from UM.Logger import Logger
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.InstanceContainer import InstanceContainer # The new profile to make.
+from cura.CuraApplication import CuraApplication
+from cura.Machines.ContainerTree import ContainerTree
from cura.ReaderWriters.ProfileReader import ProfileReader
import zipfile
@@ -17,39 +20,43 @@ import zipfile
class CuraProfileReader(ProfileReader):
## Initialises the cura profile reader.
# This does nothing since the only other function is basically stateless.
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
## Reads a cura profile from a file and returns it.
#
# \param file_name The file to read the cura profile from.
- # \return The cura profile that was in the file, if any. If the file could
- # not be read or didn't contain a valid profile, \code None \endcode is
+ # \return The cura profiles that were in the file, if any. If the file
+ # could not be read or didn't contain a valid profile, ``None`` is
# returned.
- def read(self, file_name):
+ def read(self, file_name: str) -> List[Optional[InstanceContainer]]:
try:
with zipfile.ZipFile(file_name, "r") as archive:
- results = []
+ results = [] # type: List[Optional[InstanceContainer]]
for profile_id in archive.namelist():
with archive.open(profile_id) as f:
serialized = f.read()
- profile = self._loadProfile(serialized.decode("utf-8"), profile_id)
- if profile is not None:
- results.append(profile)
+ upgraded_profiles = self._upgradeProfile(serialized.decode("utf-8"), profile_id) #After upgrading it may split into multiple profiles.
+ for upgraded_profile in upgraded_profiles:
+ serialization, new_id = upgraded_profile
+ profile = self._loadProfile(serialization, new_id)
+ if profile is not None:
+ results.append(profile)
return results
except zipfile.BadZipFile:
# It must be an older profile from Cura 2.1.
with open(file_name, encoding = "utf-8") as fhandle:
- serialized = fhandle.read()
- return [self._loadProfile(serialized, profile_id) for serialized, profile_id in self._upgradeProfile(serialized, file_name)]
+ serialized_bytes = fhandle.read()
+ return [self._loadProfile(serialized, profile_id) for serialized, profile_id in self._upgradeProfile(serialized_bytes, file_name)]
## Convert a profile from an old Cura to this Cura if needed.
#
- # \param serialized \type{str} The profile data to convert in the serialized on-disk format.
- # \param profile_id \type{str} The name of the profile.
- # \return \type{List[Tuple[str,str]]} List of serialized profile strings and matching profile names.
- def _upgradeProfile(self, serialized, profile_id):
+ # \param serialized The profile data to convert in the serialized on-disk
+ # format.
+ # \param profile_id The name of the profile.
+ # \return List of serialized profile strings and matching profile names.
+ def _upgradeProfile(self, serialized: str, profile_id: str) -> List[Tuple[str, str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -61,48 +68,67 @@ class CuraProfileReader(ProfileReader):
return []
version = int(parser["general"]["version"])
+ setting_version = int(parser["metadata"].get("setting_version", "0"))
if InstanceContainer.Version != version:
name = parser["general"]["name"]
- return self._upgradeProfileVersion(serialized, name, version)
+ return self._upgradeProfileVersion(serialized, name, version, setting_version)
else:
return [(serialized, profile_id)]
## Load a profile from a serialized string.
#
- # \param serialized \type{str} The profile data to read.
- # \param profile_id \type{str} The name of the profile.
- # \return \type{InstanceContainer|None}
- def _loadProfile(self, serialized, profile_id):
+ # \param serialized The profile data to read.
+ # \param profile_id The name of the profile.
+ # \return The profile that was stored in the string.
+ def _loadProfile(self, serialized: str, profile_id: str) -> Optional[InstanceContainer]:
# Create an empty profile.
profile = InstanceContainer(profile_id)
profile.setMetaDataEntry("type", "quality_changes")
try:
- profile.deserialize(serialized)
+ profile.deserialize(serialized, file_name = profile_id)
except ContainerFormatError as e:
Logger.log("e", "Error in the format of a container: %s", str(e))
return None
except Exception as e:
Logger.log("e", "Error while trying to parse profile: %s", str(e))
return None
+
+ global_stack = CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return None
+
+ active_quality_definition = ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
+ if profile.getMetaDataEntry("definition") != active_quality_definition:
+ profile.setMetaDataEntry("definition", active_quality_definition)
return profile
## Upgrade a serialized profile to the current profile format.
#
- # \param serialized \type{str} The profile data to convert.
- # \param profile_id \type{str} The name of the profile.
- # \param source_version \type{int} The profile version of 'serialized'.
- # \return \type{List[Tuple[str,str]]} List of serialized profile strings and matching profile names.
- def _upgradeProfileVersion(self, serialized, profile_id, source_version):
- converter_plugins = PluginRegistry.getInstance().getAllMetaData(filter={"version_upgrade": {} }, active_only=True)
+ # \param serialized The profile data to convert.
+ # \param profile_id The name of the profile.
+ # \param source_version The profile version of 'serialized'.
+ # \return List of serialized profile strings and matching profile names.
+ def _upgradeProfileVersion(self, serialized: str, profile_id: str, main_version: int, setting_version: int) -> List[Tuple[str, str]]:
+ source_version = main_version * 1000000 + setting_version
- source_format = ("profile", source_version)
- profile_convert_funcs = [plugin["version_upgrade"][source_format][2] for plugin in converter_plugins
- if source_format in plugin["version_upgrade"] and plugin["version_upgrade"][source_format][1] == InstanceContainer.Version]
-
- if not profile_convert_funcs:
+ from UM.VersionUpgradeManager import VersionUpgradeManager
+ results = VersionUpgradeManager.getInstance().updateFilesData("quality_changes", source_version, [serialized], [profile_id])
+ if results is None:
return []
- filenames, outputs = profile_convert_funcs[0](serialized, profile_id)
- if filenames is None and outputs is None:
+ serialized = results.files_data[0]
+
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+ if "general" not in parser:
+ Logger.log("w", "Missing required section 'general'.")
return []
- return list(zip(outputs, filenames))
+
+ new_source_version = results.version
+ if int(new_source_version / 1000000) != InstanceContainer.Version or new_source_version % 1000000 != CuraApplication.SettingVersion:
+ Logger.log("e", "Failed to upgrade profile [%s]", profile_id)
+
+ if int(parser["general"]["version"]) != InstanceContainer.Version:
+ Logger.log("e", "Failed to upgrade profile [%s]", profile_id)
+ return []
+ return [(serialized, profile_id)]
diff --git a/plugins/CuraProfileReader/plugin.json b/plugins/CuraProfileReader/plugin.json
index 169fb43360..e1309b2d46 100644
--- a/plugins/CuraProfileReader/plugin.json
+++ b/plugins/CuraProfileReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for importing Cura profiles.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/CuraProfileWriter/plugin.json b/plugins/CuraProfileWriter/plugin.json
index 9627c754d7..180376f266 100644
--- a/plugins/CuraProfileWriter/plugin.json
+++ b/plugins/CuraProfileWriter/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for exporting Cura profiles.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog":"cura"
}
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
index a1460cca3f..f286662bc4 100644
--- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
@@ -10,6 +10,9 @@ from UM.Version import Version
import urllib.request
from urllib.error import URLError
from typing import Dict, Optional
+import ssl
+
+import certifi
from .FirmwareUpdateCheckerLookup import FirmwareUpdateCheckerLookup, getSettingsKeyForMachine
from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
@@ -39,8 +42,12 @@ class FirmwareUpdateCheckerJob(Job):
result = self.STRING_ZERO_VERSION
try:
+ # CURA-6698 Create an SSL context and use certifi CA certificates for verification.
+ context = ssl.SSLContext(protocol = ssl.PROTOCOL_TLSv1_2)
+ context.load_verify_locations(cafile = certifi.where())
+
request = urllib.request.Request(url, headers = self._headers)
- response = urllib.request.urlopen(request)
+ response = urllib.request.urlopen(request, context = context)
result = response.read().decode("utf-8")
except URLError:
Logger.log("w", "Could not reach '{0}', if this URL is old, consider removal.".format(url))
@@ -104,7 +111,7 @@ class FirmwareUpdateCheckerJob(Job):
# because the new version of Cura will be release before the firmware and we don't want to
# notify the user when no new firmware version is available.
if (checked_version != "") and (checked_version != current_version):
- Logger.log("i", "SHOWING FIRMWARE UPDATE MESSAGE")
+ Logger.log("i", "Showing firmware update message for new version: {version}".format(version = current_version))
message = FirmwareUpdateCheckerMessage(machine_id, self._machine_name,
self._lookups.getRedirectUserUrl())
message.actionTriggered.connect(self._callback)
@@ -113,7 +120,7 @@ class FirmwareUpdateCheckerJob(Job):
Logger.log("i", "No machine with name {0} in list of firmware to check.".format(self._machine_name))
except Exception as e:
- Logger.log("w", "Failed to check for new version: %s", e)
+ Logger.logException("w", "Failed to check for new version: %s", e)
if not self.silent:
Message(i18n_catalog.i18nc("@info", "Could not access update information.")).show()
return
diff --git a/plugins/FirmwareUpdateChecker/plugin.json b/plugins/FirmwareUpdateChecker/plugin.json
index 6c55d77fd8..34e26fb146 100644
--- a/plugins/FirmwareUpdateChecker/plugin.json
+++ b/plugins/FirmwareUpdateChecker/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Checks for firmware updates.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/FirmwareUpdater/plugin.json b/plugins/FirmwareUpdater/plugin.json
index c1034e5e42..2546263064 100644
--- a/plugins/FirmwareUpdater/plugin.json
+++ b/plugins/FirmwareUpdater/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides a machine actions for updating firmware.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeGzReader/GCodeGzReader.py b/plugins/GCodeGzReader/GCodeGzReader.py
index d075e4e3b0..a528b494e9 100644
--- a/plugins/GCodeGzReader/GCodeGzReader.py
+++ b/plugins/GCodeGzReader/GCodeGzReader.py
@@ -27,6 +27,6 @@ class GCodeGzReader(MeshReader):
file_data = file.read()
uncompressed_gcode = gzip.decompress(file_data).decode("utf-8")
PluginRegistry.getInstance().getPluginObject("GCodeReader").preReadFromStream(uncompressed_gcode)
- result = PluginRegistry.getInstance().getPluginObject("GCodeReader").readFromStream(uncompressed_gcode)
+ result = PluginRegistry.getInstance().getPluginObject("GCodeReader").readFromStream(uncompressed_gcode, file_name)
return result
diff --git a/plugins/GCodeGzReader/plugin.json b/plugins/GCodeGzReader/plugin.json
index d4f281682f..b3d52b1627 100644
--- a/plugins/GCodeGzReader/plugin.json
+++ b/plugins/GCodeGzReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Reads g-code from a compressed archive.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeGzWriter/plugin.json b/plugins/GCodeGzWriter/plugin.json
index b0e6f8d605..de59d1eda8 100644
--- a/plugins/GCodeGzWriter/plugin.json
+++ b/plugins/GCodeGzWriter/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Writes g-code to a compressed archive.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeProfileReader/plugin.json b/plugins/GCodeProfileReader/plugin.json
index af1c2d1827..162c31ce35 100644
--- a/plugins/GCodeProfileReader/plugin.json
+++ b/plugins/GCodeProfileReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for importing profiles from g-code files.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py
index f8618712a1..d05338ae4d 100644
--- a/plugins/GCodeReader/FlavorParser.py
+++ b/plugins/GCodeReader/FlavorParser.py
@@ -1,31 +1,33 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+import math
+import re
+from typing import Dict, List, NamedTuple, Optional, Union, Set
+
+import numpy
+
from UM.Backend import Backend
from UM.Job import Job
from UM.Logger import Logger
from UM.Math.Vector import Vector
from UM.Message import Message
-from cura.Scene.CuraSceneNode import CuraSceneNode
from UM.i18n import i18nCatalog
-catalog = i18nCatalog("cura")
-
from cura.CuraApplication import CuraApplication
from cura.LayerDataBuilder import LayerDataBuilder
from cura.LayerDataDecorator import LayerDataDecorator
from cura.LayerPolygon import LayerPolygon
+from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.GCodeListDecorator import GCodeListDecorator
from cura.Settings.ExtruderManager import ExtruderManager
-import numpy
-import math
-import re
-from typing import Dict, List, NamedTuple, Optional, Union
+catalog = i18nCatalog("cura")
PositionOptional = NamedTuple("Position", [("x", Optional[float]), ("y", Optional[float]), ("z", Optional[float]), ("f", Optional[float]), ("e", Optional[float])])
Position = NamedTuple("Position", [("x", float), ("y", float), ("z", float), ("f", float), ("e", List[float])])
+
## This parser is intended to interpret the common firmware codes among all the
# different flavors
class FlavorParser:
@@ -33,9 +35,11 @@ class FlavorParser:
def __init__(self) -> None:
CuraApplication.getInstance().hideMessageSignal.connect(self._onHideMessage)
self._cancelled = False
- self._message = None
+ self._message = None # type: Optional[Message]
self._layer_number = 0
self._extruder_number = 0
+ # All extruder numbers that have been seen
+ self._extruders_seen = {0} # type: Set[int]
self._clearValues()
self._scene_node = None
# X, Y, Z position, F feedrate and E extruder values are stored
@@ -64,7 +68,7 @@ class FlavorParser:
if n < 0:
return None
n += len(code)
- pattern = re.compile("[;\s]")
+ pattern = re.compile("[;\\s]")
match = pattern.search(line, n)
m = match.start() if match is not None else -1
try:
@@ -290,7 +294,12 @@ class FlavorParser:
extruder.getProperty("machine_nozzle_offset_y", "value")]
return result
- def processGCodeStream(self, stream: str) -> Optional[CuraSceneNode]:
+ #
+ # CURA-6643
+ # This function needs the filename so it can be set to the SceneNode. Otherwise, if you load a GCode file and press
+ # F5, that gcode SceneNode will be removed because it doesn't have a file to be reloaded from.
+ #
+ def processGCodeStream(self, stream: str, filename: str) -> Optional["CuraSceneNode"]:
Logger.log("d", "Preparing to load GCode")
self._cancelled = False
# We obtain the filament diameter from the selected extruder to calculate line widths
@@ -368,6 +377,8 @@ class FlavorParser:
self._layer_type = LayerPolygon.InfillType
elif type == "SUPPORT-INTERFACE":
self._layer_type = LayerPolygon.SupportInterfaceType
+ elif type == "PRIME-TOWER":
+ self._layer_type = LayerPolygon.PrimeTowerType
else:
Logger.log("w", "Encountered a unknown type (%s) while parsing g-code.", type)
@@ -414,6 +425,7 @@ class FlavorParser:
if line.startswith("T"):
T = self._getInt(line, "T")
if T is not None:
+ self._extruders_seen.add(T)
self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0]))
current_path.clear()
@@ -425,7 +437,8 @@ class FlavorParser:
if line.startswith("M"):
M = self._getInt(line, "M")
- self.processMCode(M, line, current_position, current_path)
+ if M is not None:
+ self.processMCode(M, line, current_position, current_path)
# "Flush" leftovers. Last layer paths are still stored
if len(current_path) > 1:
@@ -448,6 +461,7 @@ class FlavorParser:
scene_node.addDecorator(decorator)
gcode_list_decorator = GCodeListDecorator()
+ gcode_list_decorator.setGcodeFileName(filename)
gcode_list_decorator.setGCodeList(gcode_list)
scene_node.addDecorator(gcode_list_decorator)
@@ -462,10 +476,9 @@ class FlavorParser:
if self._layer_number == 0:
Logger.log("w", "File doesn't contain any valid layers")
- settings = CuraApplication.getInstance().getGlobalContainerStack()
- if not settings.getProperty("machine_center_is_zero", "value"):
- machine_width = settings.getProperty("machine_width", "value")
- machine_depth = settings.getProperty("machine_depth", "value")
+ if not global_stack.getProperty("machine_center_is_zero", "value"):
+ machine_width = global_stack.getProperty("machine_width", "value")
+ machine_depth = global_stack.getProperty("machine_depth", "value")
scene_node.setPosition(Vector(-machine_width / 2, 0, machine_depth / 2))
Logger.log("d", "GCode loading finished")
diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py
index 1bc22a3e62..21be026cc6 100755
--- a/plugins/GCodeReader/GCodeReader.py
+++ b/plugins/GCodeReader/GCodeReader.py
@@ -2,6 +2,8 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional, Union, List, TYPE_CHECKING
+
from UM.FileHandler.FileReader import FileReader
from UM.Mesh.MeshReader import MeshReader
from UM.i18n import i18nCatalog
@@ -9,10 +11,13 @@ from UM.Application import Application
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
catalog = i18nCatalog("cura")
+
+from .FlavorParser import FlavorParser
from . import MarlinFlavorParser, RepRapFlavorParser
-
-
+if TYPE_CHECKING:
+ from UM.Scene.SceneNode import SceneNode
+ from cura.Scene.CuraSceneNode import CuraSceneNode
# Class for loading and parsing G-code files
@@ -33,7 +38,7 @@ class GCodeReader(MeshReader):
)
self._supported_extensions = [".gcode", ".g"]
- self._flavor_reader = None
+ self._flavor_reader = None # type: Optional[FlavorParser]
Application.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
@@ -57,10 +62,16 @@ class GCodeReader(MeshReader):
file_data = file.read()
return self.preReadFromStream(file_data, args, kwargs)
- def readFromStream(self, stream):
- return self._flavor_reader.processGCodeStream(stream)
+ def readFromStream(self, stream: str, filename: str) -> Optional["CuraSceneNode"]:
+ if self._flavor_reader is None:
+ return None
+ return self._flavor_reader.processGCodeStream(stream, filename)
- def _read(self, file_name):
+ def _read(self, file_name: str) -> Union["SceneNode", List["SceneNode"]]:
with open(file_name, "r", encoding = "utf-8") as file:
file_data = file.read()
- return self.readFromStream(file_data)
+ result = [] # type: List[SceneNode]
+ node = self.readFromStream(file_data, file_name)
+ if node is not None:
+ result.append(node)
+ return result
diff --git a/plugins/GCodeReader/plugin.json b/plugins/GCodeReader/plugin.json
index bbc94fa917..e34fefbdff 100644
--- a/plugins/GCodeReader/plugin.json
+++ b/plugins/GCodeReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Victor Larchenko, Ultimaker",
"version": "1.0.1",
"description": "Allows loading and displaying G-code files.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py
index 3e5bf59e73..792b2aff10 100644
--- a/plugins/GCodeWriter/GCodeWriter.py
+++ b/plugins/GCodeWriter/GCodeWriter.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import re # For escaping characters in the settings.
@@ -9,8 +9,7 @@ from UM.Mesh.MeshWriter import MeshWriter
from UM.Logger import Logger
from UM.Application import Application
from UM.Settings.InstanceContainer import InstanceContainer
-
-from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
+from cura.Machines.ContainerTree import ContainerTree
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
@@ -117,17 +116,24 @@ class GCodeWriter(MeshWriter):
# \return A serialised string of the settings.
def _serialiseSettings(self, stack):
container_registry = self._application.getContainerRegistry()
- quality_manager = self._application.getQualityManager()
prefix = self._setting_keyword + str(GCodeWriter.version) + " " # The prefix to put before each line.
prefix_length = len(prefix)
quality_type = stack.quality.getMetaDataEntry("quality_type")
container_with_profile = stack.qualityChanges
+ machine_definition_id_for_quality = ContainerTree.getInstance().machines[stack.definition.getId()].quality_definition
if container_with_profile.getId() == "empty_quality_changes":
# If the global quality changes is empty, create a new one
quality_name = container_registry.uniqueName(stack.quality.getName())
- container_with_profile = quality_manager._createQualityChanges(quality_type, quality_name, stack, None)
+ quality_id = container_registry.uniqueName((stack.definition.getId() + "_" + quality_name).lower().replace(" ", "_"))
+ container_with_profile = InstanceContainer(quality_id)
+ container_with_profile.setName(quality_name)
+ container_with_profile.setMetaDataEntry("type", "quality_changes")
+ container_with_profile.setMetaDataEntry("quality_type", quality_type)
+ if stack.getMetaDataEntry("position") is not None: # For extruder stacks, the quality changes should include an intent category.
+ container_with_profile.setMetaDataEntry("intent_category", stack.intent.getMetaDataEntry("intent_category", "default"))
+ container_with_profile.setDefinition(machine_definition_id_for_quality)
flat_global_container = self._createFlattenedContainerInstance(stack.userChanges, container_with_profile)
# If the quality changes is not set, we need to set type manually
@@ -139,7 +145,6 @@ class GCodeWriter(MeshWriter):
flat_global_container.setMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal"))
# Get the machine definition ID for quality profiles
- machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(stack.definition)
flat_global_container.setMetaDataEntry("definition", machine_definition_id_for_quality)
serialized = flat_global_container.serialize()
@@ -151,7 +156,12 @@ class GCodeWriter(MeshWriter):
if extruder_quality.getId() == "empty_quality_changes":
# Same story, if quality changes is empty, create a new one
quality_name = container_registry.uniqueName(stack.quality.getName())
- extruder_quality = quality_manager._createQualityChanges(quality_type, quality_name, stack, None)
+ quality_id = container_registry.uniqueName((stack.definition.getId() + "_" + quality_name).lower().replace(" ", "_"))
+ extruder_quality = InstanceContainer(quality_id)
+ extruder_quality.setName(quality_name)
+ extruder_quality.setMetaDataEntry("type", "quality_changes")
+ extruder_quality.setMetaDataEntry("quality_type", quality_type)
+ extruder_quality.setDefinition(machine_definition_id_for_quality)
flat_extruder_quality = self._createFlattenedContainerInstance(extruder.userChanges, extruder_quality)
# If the quality changes is not set, we need to set type manually
diff --git a/plugins/GCodeWriter/plugin.json b/plugins/GCodeWriter/plugin.json
index f3a95ddb78..457652bf3f 100644
--- a/plugins/GCodeWriter/plugin.json
+++ b/plugins/GCodeWriter/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Writes g-code to a file.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/ImageReader/ConfigUI.qml b/plugins/ImageReader/ConfigUI.qml
index b9ff2e4453..0429fae4e1 100644
--- a/plugins/ImageReader/ConfigUI.qml
+++ b/plugins/ImageReader/ConfigUI.qml
@@ -123,7 +123,7 @@ UM.Dialog
UM.TooltipArea {
Layout.fillWidth:true
height: childrenRect.height
- text: catalog.i18nc("@info:tooltip","By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh.")
+ text: catalog.i18nc("@info:tooltip","For lithophanes dark pixels should correspond to thicker locations in order to block more light coming through. For height maps lighter pixels signify higher terrain, so lighter pixels should correspond to thicker locations in the generated 3D model.")
Row {
width: parent.width
@@ -134,15 +134,61 @@ UM.Dialog
anchors.verticalCenter: parent.verticalCenter
}
ComboBox {
- id: image_color_invert
- objectName: "Image_Color_Invert"
- model: [ catalog.i18nc("@item:inlistbox","Lighter is higher"), catalog.i18nc("@item:inlistbox","Darker is higher") ]
+ id: lighter_is_higher
+ objectName: "Lighter_Is_Higher"
+ model: [ catalog.i18nc("@item:inlistbox","Darker is higher"), catalog.i18nc("@item:inlistbox","Lighter is higher") ]
width: 180 * screenScaleFactor
onCurrentIndexChanged: { manager.onImageColorInvertChanged(currentIndex) }
}
}
}
+ UM.TooltipArea {
+ Layout.fillWidth:true
+ height: childrenRect.height
+ text: catalog.i18nc("@info:tooltip","For lithophanes a simple logarithmic model for translucency is available. For height maps the pixel values correspond to heights linearly.")
+ Row {
+ width: parent.width
+
+ Label {
+ text: "Color Model"
+ width: 150 * screenScaleFactor
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ ComboBox {
+ id: color_model
+ objectName: "ColorModel"
+ model: [ catalog.i18nc("@item:inlistbox","Linear"), catalog.i18nc("@item:inlistbox","Translucency") ]
+ width: 180 * screenScaleFactor
+ onCurrentIndexChanged: { manager.onColorModelChanged(currentIndex) }
+ }
+ }
+ }
+
+ UM.TooltipArea {
+ Layout.fillWidth:true
+ height: childrenRect.height
+ text: catalog.i18nc("@info:tooltip","The percentage of light penetrating a print with a thickness of 1 millimeter. Lowering this value increases the contrast in dark regions and decreases the contrast in light regions of the image.")
+ visible: color_model.currentText == catalog.i18nc("@item:inlistbox","Translucency")
+ Row {
+ width: parent.width
+
+ Label {
+ text: catalog.i18nc("@action:label", "1mm Transmittance (%)")
+ width: 150 * screenScaleFactor
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ TextField {
+ id: transmittance
+ objectName: "Transmittance"
+ focus: true
+ validator: RegExpValidator {regExp: /^[1-9]\d{0,2}([\,|\.]\d*)?$/}
+ width: 180 * screenScaleFactor
+ onTextChanged: { manager.onTransmittanceChanged(text) }
+ }
+ }
+ }
+
UM.TooltipArea {
Layout.fillWidth:true
height: childrenRect.height
diff --git a/plugins/ImageReader/ImageReader.py b/plugins/ImageReader/ImageReader.py
index 5195b61595..d6c2827d16 100644
--- a/plugins/ImageReader/ImageReader.py
+++ b/plugins/ImageReader/ImageReader.py
@@ -3,6 +3,8 @@
import numpy
+import math
+
from PyQt5.QtGui import QImage, qRed, qGreen, qBlue
from PyQt5.QtCore import Qt
@@ -46,9 +48,9 @@ class ImageReader(MeshReader):
def _read(self, file_name):
size = max(self._ui.getWidth(), self._ui.getDepth())
- return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.image_color_invert)
+ return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.lighter_is_higher, self._ui.use_transparency_model, self._ui.transmittance_1mm)
- def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, image_color_invert):
+ def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, lighter_is_higher, use_transparency_model, transmittance_1mm):
scene_node = SceneNode()
mesh = MeshBuilder()
@@ -99,12 +101,14 @@ class ImageReader(MeshReader):
for x in range(0, width):
for y in range(0, height):
qrgb = img.pixel(x, y)
- avg = float(qRed(qrgb) + qGreen(qrgb) + qBlue(qrgb)) / (3 * 255)
- height_data[y, x] = avg
+ if use_transparency_model:
+ height_data[y, x] = (0.299 * math.pow(qRed(qrgb) / 255.0, 2.2) + 0.587 * math.pow(qGreen(qrgb) / 255.0, 2.2) + 0.114 * math.pow(qBlue(qrgb) / 255.0, 2.2))
+ else:
+ height_data[y, x] = (0.212655 * qRed(qrgb) + 0.715158 * qGreen(qrgb) + 0.072187 * qBlue(qrgb)) / 255 # fast computation ignoring gamma and degamma
Job.yieldThread()
- if image_color_invert:
+ if lighter_is_higher == use_transparency_model:
height_data = 1 - height_data
for _ in range(0, blur_iterations):
@@ -124,8 +128,15 @@ class ImageReader(MeshReader):
Job.yieldThread()
- height_data *= scale_vector.y
- height_data += base_height
+ if use_transparency_model:
+ divisor = 1.0 / math.log(transmittance_1mm / 100.0) # log-base doesn't matter here. Precompute this value for faster computation of each pixel.
+ min_luminance = (transmittance_1mm / 100.0) ** (peak_height - base_height)
+ for (y, x) in numpy.ndindex(height_data.shape):
+ mapped_luminance = min_luminance + (1.0 - min_luminance) * height_data[y, x]
+ height_data[y, x] = base_height + divisor * math.log(mapped_luminance) # use same base as a couple lines above this
+ else:
+ height_data *= scale_vector.y
+ height_data += base_height
heightmap_face_count = 2 * height_minus_one * width_minus_one
total_face_count = heightmap_face_count + (width_minus_one * 2) * (height_minus_one * 2) + 2
diff --git a/plugins/ImageReader/ImageReaderUI.py b/plugins/ImageReader/ImageReaderUI.py
index cb45afa4ad..a61fabb742 100644
--- a/plugins/ImageReader/ImageReaderUI.py
+++ b/plugins/ImageReader/ImageReaderUI.py
@@ -30,10 +30,12 @@ class ImageReaderUI(QObject):
self._width = self.default_width
self._depth = self.default_depth
- self.base_height = 1
- self.peak_height = 10
+ self.base_height = 0.4
+ self.peak_height = 2.5
self.smoothing = 1
- self.image_color_invert = False;
+ self.lighter_is_higher = False;
+ self.use_transparency_model = True;
+ self.transmittance_1mm = 50.0; # based on pearl PLA
self._ui_lock = threading.Lock()
self._cancelled = False
@@ -75,6 +77,7 @@ class ImageReaderUI(QObject):
self._ui_view.findChild(QObject, "Base_Height").setProperty("text", str(self.base_height))
self._ui_view.findChild(QObject, "Peak_Height").setProperty("text", str(self.peak_height))
+ self._ui_view.findChild(QObject, "Transmittance").setProperty("text", str(self.transmittance_1mm))
self._ui_view.findChild(QObject, "Smoothing").setProperty("value", self.smoothing)
def _createConfigUI(self):
@@ -143,4 +146,12 @@ class ImageReaderUI(QObject):
@pyqtSlot(int)
def onImageColorInvertChanged(self, value):
- self.image_color_invert = (value == 1)
+ self.lighter_is_higher = (value == 1)
+
+ @pyqtSlot(int)
+ def onColorModelChanged(self, value):
+ self.use_transparency_model = (value == 0)
+
+ @pyqtSlot(int)
+ def onTransmittanceChanged(self, value):
+ self.transmittance_1mm = value
diff --git a/plugins/ImageReader/plugin.json b/plugins/ImageReader/plugin.json
index d966537d99..a5f03a540d 100644
--- a/plugins/ImageReader/plugin.json
+++ b/plugins/ImageReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Enables ability to generate printable geometry from 2D image files.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py
index 013bab6f11..87b26eb4ec 100644
--- a/plugins/LegacyProfileReader/LegacyProfileReader.py
+++ b/plugins/LegacyProfileReader/LegacyProfileReader.py
@@ -157,7 +157,7 @@ class LegacyProfileReader(ProfileReader):
data = stream.getvalue()
profile = InstanceContainer(profile_id)
- profile.deserialize(data) # Also performs the version upgrade.
+ profile.deserialize(data, file_name) # Also performs the version upgrade.
profile.setDirty(True)
#We need to return one extruder stack and one global stack.
diff --git a/plugins/LegacyProfileReader/plugin.json b/plugins/LegacyProfileReader/plugin.json
index 2f5264ad37..f4f18becbf 100644
--- a/plugins/LegacyProfileReader/plugin.json
+++ b/plugins/LegacyProfileReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for importing profiles from legacy Cura versions.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py b/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py
index 480a61f301..cd0f681828 100644
--- a/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py
+++ b/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py
@@ -5,6 +5,8 @@ import configparser # An input for some functions we're testing.
import os.path # To find the integration test .ini files.
import pytest # To register tests with.
import unittest.mock # To mock the application, plug-in and container registry out.
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import UM.Application # To mock the application out.
import UM.PluginRegistry # To mock the plug-in registry out.
@@ -12,11 +14,14 @@ import UM.Settings.ContainerRegistry # To mock the container registry out.
import UM.Settings.InstanceContainer # To intercept the serialised data from the read() function.
import LegacyProfileReader as LegacyProfileReaderModule # To get the directory of the module.
-from LegacyProfileReader import LegacyProfileReader # The module we're testing.
+
@pytest.fixture
def legacy_profile_reader():
- return LegacyProfileReader()
+ try:
+ return LegacyProfileReaderModule.LegacyProfileReader()
+ except TypeError:
+ return LegacyProfileReaderModule.LegacyProfileReader.LegacyProfileReader()
test_prepareDefaultsData = [
{
@@ -157,7 +162,7 @@ def test_read(legacy_profile_reader, file_name):
plugin_registry.getPluginPath = unittest.mock.MagicMock(return_value = os.path.dirname(LegacyProfileReaderModule.__file__))
# Mock out the resulting InstanceContainer so that we can intercept the data before it's passed through the version upgrader.
- def deserialize(self, data): # Intercepts the serialised data that we'd perform the version upgrade from when deserializing.
+ def deserialize(self, data, filename): # Intercepts the serialised data that we'd perform the version upgrade from when deserializing.
global intercepted_data
intercepted_data = data
@@ -187,4 +192,4 @@ def test_read(legacy_profile_reader, file_name):
assert parser["metadata"]["type"] == "quality_changes"
assert parser["metadata"]["quality_type"] == "normal"
assert parser["metadata"]["position"] == "0"
- assert parser["metadata"]["setting_version"] == "5" # Yes, before we upgraded.
\ No newline at end of file
+ assert parser["metadata"]["setting_version"] == "5" # Yes, before we upgraded.
diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py
index afd7aac86d..28535024a7 100755
--- a/plugins/MachineSettingsAction/MachineSettingsAction.py
+++ b/plugins/MachineSettingsAction/MachineSettingsAction.py
@@ -1,16 +1,24 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import pyqtProperty, pyqtSignal
+from typing import Optional, TYPE_CHECKING
+
+from PyQt5.QtCore import pyqtProperty
import UM.i18n
from UM.FlameProfiler import pyqtSlot
-from UM.Application import Application
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.DefinitionContainer import DefinitionContainer
+from UM.Util import parseBool
+import cura.CuraApplication # Imported like this to prevent circular dependencies.
from cura.MachineAction import MachineAction
+from cura.Machines.ContainerTree import ContainerTree # To re-build the machine node when hasMaterials changes.
from cura.Settings.CuraStackBuilder import CuraStackBuilder
+from cura.Settings.cura_empty_instance_containers import isEmptyContainer
+
+if TYPE_CHECKING:
+ from PyQt5.QtCore import QObject
catalog = UM.i18n.i18nCatalog("cura")
@@ -18,139 +26,118 @@ catalog = UM.i18n.i18nCatalog("cura")
## This action allows for certain settings that are "machine only") to be modified.
# It automatically detects machine definitions that it knows how to change and attaches itself to those.
class MachineSettingsAction(MachineAction):
- def __init__(self, parent = None):
+ def __init__(self, parent: Optional["QObject"] = None) -> None:
super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
self._qml_url = "MachineSettingsAction.qml"
- self._application = Application.getInstance()
-
- self._global_container_stack = None
+ from cura.CuraApplication import CuraApplication
+ self._application = CuraApplication.getInstance()
from cura.Settings.CuraContainerStack import _ContainerIndexes
- self._container_index = _ContainerIndexes.DefinitionChanges
+ self._store_container_index = _ContainerIndexes.DefinitionChanges
self._container_registry = ContainerRegistry.getInstance()
self._container_registry.containerAdded.connect(self._onContainerAdded)
- self._container_registry.containerRemoved.connect(self._onContainerRemoved)
- self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
+ # The machine settings dialog blocks auto-slicing when it's shown, and re-enables it when it's finished.
self._backend = self._application.getBackend()
+ self.onFinished.connect(self._onFinished)
- self._empty_definition_container_id_list = []
+ # If the g-code flavour changes between UltiGCode and another flavour, we need to update the container tree.
+ self._application.globalContainerStackChanged.connect(self._updateHasMaterialsInContainerTree)
- def _isEmptyDefinitionChanges(self, container_id: str):
- if not self._empty_definition_container_id_list:
- self._empty_definition_container_id_list = [self._application.empty_container.getId(),
- self._application.empty_definition_changes_container.getId()]
- return container_id in self._empty_definition_container_id_list
+ # Which container index in a stack to store machine setting changes.
+ @pyqtProperty(int, constant = True)
+ def storeContainerIndex(self) -> int:
+ return self._store_container_index
def _onContainerAdded(self, container):
# Add this action as a supported action to all machine definitions
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
self._application.getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
- def _onContainerRemoved(self, container):
- # Remove definition_changes containers when a stack is removed
- if container.getMetaDataEntry("type") in ["machine", "extruder_train"]:
- definition_changes_id = container.definitionChanges.getId()
- if self._isEmptyDefinitionChanges(definition_changes_id):
- return
+ ## Triggered when the global container stack changes or when the g-code
+ # flavour setting is changed.
+ def _updateHasMaterialsInContainerTree(self) -> None:
+ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ if global_stack is None:
+ return
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
+
+ if machine_node.has_materials != parseBool(global_stack.getMetaDataEntry("has_materials")): # May have changed due to the g-code flavour.
+ machine_node.has_materials = parseBool(global_stack.getMetaDataEntry("has_materials"))
+ machine_node._loadAll()
def _reset(self):
- if not self._global_container_stack:
+ global_stack = self._application.getMachineManager().activeMachine
+ if not global_stack:
return
# Make sure there is a definition_changes container to store the machine settings
- definition_changes_id = self._global_container_stack.definitionChanges.getId()
- if self._isEmptyDefinitionChanges(definition_changes_id):
- CuraStackBuilder.createDefinitionChangesContainer(self._global_container_stack,
- self._global_container_stack.getName() + "_settings")
-
- # Notify the UI in which container to store the machine settings data
- from cura.Settings.CuraContainerStack import _ContainerIndexes
-
- container_index = _ContainerIndexes.DefinitionChanges
- if container_index != self._container_index:
- self._container_index = container_index
- self.containerIndexChanged.emit()
+ definition_changes_id = global_stack.definitionChanges.getId()
+ if isEmptyContainer(definition_changes_id):
+ CuraStackBuilder.createDefinitionChangesContainer(global_stack,
+ global_stack.getName() + "_settings")
# Disable auto-slicing while the MachineAction is showing
if self._backend: # This sometimes triggers before backend is loaded.
self._backend.disableTimer()
- @pyqtSlot()
- def onFinishAction(self):
- # Restore autoslicing when the machineaction is dismissed
+ def _onFinished(self):
+ # Restore auto-slicing when the machine action is dismissed
if self._backend and self._backend.determineAutoSlicing():
+ self._backend.enableTimer()
self._backend.tickle()
- containerIndexChanged = pyqtSignal()
-
- @pyqtProperty(int, notify = containerIndexChanged)
- def containerIndex(self):
- return self._container_index
-
- def _onGlobalContainerChanged(self):
- self._global_container_stack = Application.getInstance().getGlobalContainerStack()
-
- # This additional emit is needed because we cannot connect a UM.Signal directly to a pyqtSignal
- self.globalContainerChanged.emit()
-
- globalContainerChanged = pyqtSignal()
-
- @pyqtProperty(int, notify = globalContainerChanged)
- def definedExtruderCount(self):
- if not self._global_container_stack:
- return 0
-
- return len(self._global_container_stack.getMetaDataEntry("machine_extruder_trains"))
-
@pyqtSlot(int)
- def setMachineExtruderCount(self, extruder_count):
+ def setMachineExtruderCount(self, extruder_count: int) -> None:
# Note: this method was in this class before, but since it's quite generic and other plugins also need it
# it was moved to the machine manager instead. Now this method just calls the machine manager.
self._application.getMachineManager().setActiveMachineExtruderCount(extruder_count)
@pyqtSlot()
- def forceUpdate(self):
+ def forceUpdate(self) -> None:
# Force rebuilding the build volume by reloading the global container stack.
# This is a bit of a hack, but it seems quick enough.
- self._application.globalContainerStackChanged.emit()
+ self._application.getMachineManager().globalContainerChanged.emit()
@pyqtSlot()
- def updateHasMaterialsMetadata(self):
+ def updateHasMaterialsMetadata(self) -> None:
+ global_stack = self._application.getMachineManager().activeMachine
+
# Updates the has_materials metadata flag after switching gcode flavor
- if not self._global_container_stack:
+ if not global_stack:
return
- definition = self._global_container_stack.getBottom()
- if definition.getProperty("machine_gcode_flavor", "value") != "UltiGCode" or definition.getMetaDataEntry("has_materials", False):
+ definition = global_stack.getDefinition()
+ if definition.getProperty("machine_gcode_flavor", "value") != "UltiGCode" or parseBool(definition.getMetaDataEntry("has_materials", False)):
# In other words: only continue for the UM2 (extended), but not for the UM2+
return
machine_manager = self._application.getMachineManager()
- material_manager = self._application.getMaterialManager()
- extruder_positions = list(self._global_container_stack.extruders.keys())
- has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
+ has_materials = global_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
- material_node = None
if has_materials:
- self._global_container_stack.setMetaDataEntry("has_materials", True)
+ global_stack.setMetaDataEntry("has_materials", True)
else:
# The metadata entry is stored in an ini, and ini files are parsed as strings only.
# Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
- if "has_materials" in self._global_container_stack.getMetaData():
- self._global_container_stack.removeMetaDataEntry("has_materials")
+ if "has_materials" in global_stack.getMetaData():
+ global_stack.removeMetaDataEntry("has_materials")
+
+ self._updateHasMaterialsInContainerTree()
# set materials
- for position in extruder_positions:
- if has_materials:
- material_node = material_manager.getDefaultMaterial(self._global_container_stack, position, None)
- machine_manager.setMaterial(position, material_node)
+ machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
+ for position, extruder in enumerate(global_stack.extruderList):
+ #Find out what material we need to default to.
+ approximate_diameter = round(extruder.getProperty("material_diameter", "value"))
+ material_node = machine_node.variants[extruder.variant.getName()].preferredMaterial(approximate_diameter)
+ machine_manager.setMaterial(str(position), material_node)
self._application.globalContainerStackChanged.emit()
@pyqtSlot(int)
- def updateMaterialForDiameter(self, extruder_position: int):
+ def updateMaterialForDiameter(self, extruder_position: int) -> None:
# Updates the material container to a material that matches the material diameter set for the printer
self._application.getMachineManager().updateMaterialWithVariant(str(extruder_position))
diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml
index ef8fda224a..56b4d3e3b6 100644
--- a/plugins/MachineSettingsAction/MachineSettingsAction.qml
+++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml
@@ -1,939 +1,119 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
-import UM 1.2 as UM
-import Cura 1.0 as Cura
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+//
+// This component contains the content for the "Welcome" page of the welcome on-boarding process.
+//
Cura.MachineAction
{
- id: base
- property var extrudersModel: Cura.ExtrudersModel{} // Do not retrieve the Model from a backend. Otherwise the tabs
- // in tabView will not removed/updated. Probably QML bug
- property int extruderTabsCount: 0
+ UM.I18nCatalog { id: catalog; name: "cura" }
- property var activeMachineId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.id : ""
+ anchors.fill: parent
+ property var extrudersModel: Cura.ExtrudersModel {}
+
+ // If we create a TabButton for "Printer" and use Repeater for extruders, for some reason, once the component
+ // finishes it will automatically change "currentIndex = 1", and it is VERY difficult to change "currentIndex = 0"
+ // after that. Using a model and a Repeater to create both "Printer" and extruder TabButtons seem to solve this
+ // problem.
Connections
{
- target: base.extrudersModel
- onModelChanged:
- {
- var extruderCount = base.extrudersModel.count;
- base.extruderTabsCount = extruderCount;
- }
+ target: extrudersModel
+ onItemsChanged: tabNameModel.update()
}
- Connections
+ ListModel
{
- target: dialog ? dialog : null
- ignoreUnknownSignals: true
- // Any which way this action dialog is dismissed, make sure it is properly finished
- onNextClicked: finishAction()
- onBackClicked: finishAction()
- onAccepted: finishAction()
- onRejected: finishAction()
- onClosing: finishAction()
- }
+ id: tabNameModel
- function finishAction()
- {
- forceActiveFocus();
- manager.onFinishAction();
- }
+ Component.onCompleted: update()
- anchors.fill: parent;
- Item
- {
- id: machineSettingsAction
- anchors.fill: parent;
-
- UM.I18nCatalog { id: catalog; name: "cura"; }
-
- Label
+ function update()
{
- id: pageTitle
- width: parent.width
- text: catalog.i18nc("@title", "Machine Settings")
- wrapMode: Text.WordWrap
- font.pointSize: 18;
- }
-
- TabView
- {
- id: settingsTabs
- height: parent.height - y
- width: parent.width
- anchors.left: parent.left
- anchors.top: pageTitle.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
-
- property real columnWidth: Math.round((width - 3 * UM.Theme.getSize("default_margin").width) / 2)
- property real labelColumnWidth: Math.round(columnWidth / 2)
-
- Tab
+ clear()
+ append({ name: catalog.i18nc("@title:tab", "Printer") })
+ for (var i = 0; i < extrudersModel.count; i++)
{
- title: catalog.i18nc("@title:tab", "Printer");
- anchors.margins: UM.Theme.getSize("default_margin").width
-
- Column
- {
- spacing: UM.Theme.getSize("default_margin").height
-
- Row
- {
- width: parent.width
- spacing: UM.Theme.getSize("default_margin").height
-
- Column
- {
- width: settingsTabs.columnWidth
- spacing: UM.Theme.getSize("default_lining").height
-
- Label
- {
- text: catalog.i18nc("@label", "Printer Settings")
- font.bold: true
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Loader
- {
- id: buildAreaWidthField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_width"
- property string label: catalog.i18nc("@label", "X (Width)")
- property string unit: catalog.i18nc("@label", "mm")
- property bool forceUpdateOnChange: true
- }
-
- Loader
- {
- id: buildAreaDepthField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_depth"
- property string label: catalog.i18nc("@label", "Y (Depth)")
- property string unit: catalog.i18nc("@label", "mm")
- property bool forceUpdateOnChange: true
- }
-
- Loader
- {
- id: buildAreaHeightField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_height"
- property string label: catalog.i18nc("@label", "Z (Height)")
- property string unit: catalog.i18nc("@label", "mm")
- property bool forceUpdateOnChange: true
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Loader
- {
- id: shapeComboBox
- sourceComponent: comboBoxWithOptions
- property string settingKey: "machine_shape"
- property string label: catalog.i18nc("@label", "Build plate shape")
- property bool forceUpdateOnChange: true
- }
-
- Loader
- {
- id: centerIsZeroCheckBox
- sourceComponent: simpleCheckBox
- property string settingKey: "machine_center_is_zero"
- property string label: catalog.i18nc("@option:check", "Origin at center")
- property bool forceUpdateOnChange: true
- }
- Loader
- {
- id: heatedBedCheckBox
- sourceComponent: simpleCheckBox
- property var settingKey: "machine_heated_bed"
- property string label: catalog.i18nc("@option:check", "Heated bed")
- property bool forceUpdateOnChange: true
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Loader
- {
- id: gcodeFlavorComboBox
- sourceComponent: comboBoxWithOptions
- property string settingKey: "machine_gcode_flavor"
- property string label: catalog.i18nc("@label", "G-code flavor")
- property bool forceUpdateOnChange: true
- property var afterOnActivate: manager.updateHasMaterialsMetadata
- }
- }
-
- Column
- {
- width: settingsTabs.columnWidth
- spacing: UM.Theme.getSize("default_lining").height
-
- Label
- {
- text: catalog.i18nc("@label", "Printhead Settings")
- font.bold: true
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Loader
- {
- id: printheadXMinField
- sourceComponent: headPolygonTextField
- property string label: catalog.i18nc("@label", "X min")
- property string tooltip: catalog.i18nc("@tooltip", "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
- property string axis: "x"
- property string side: "min"
- }
-
- Loader
- {
- id: printheadYMinField
- sourceComponent: headPolygonTextField
- property string label: catalog.i18nc("@label", "Y min")
- property string tooltip: catalog.i18nc("@tooltip", "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
- property string axis: "y"
- property string side: "min"
- }
-
- Loader
- {
- id: printheadXMaxField
- sourceComponent: headPolygonTextField
- property string label: catalog.i18nc("@label", "X max")
- property string tooltip: catalog.i18nc("@tooltip", "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
- property string axis: "x"
- property string side: "max"
- }
-
- Loader
- {
- id: printheadYMaxField
- sourceComponent: headPolygonTextField
- property string label: catalog.i18nc("@label", "Y max")
- property string tooltip: catalog.i18nc("@tooltip", "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
- property string axis: "y"
- property string side: "max"
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Loader
- {
- id: gantryHeightField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "gantry_height"
- property string label: catalog.i18nc("@label", "Gantry height")
- property string unit: catalog.i18nc("@label", "mm")
- property string tooltip: catalog.i18nc("@tooltip", "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\".")
- property bool forceUpdateOnChange: true
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- UM.TooltipArea
- {
- height: childrenRect.height
- width: childrenRect.width
- text: machineExtruderCountProvider.properties.description
- visible: extruderCountModel.count >= 2
-
- Row
- {
- spacing: UM.Theme.getSize("default_margin").width
-
- Label
- {
- text: catalog.i18nc("@label", "Number of Extruders")
- elide: Text.ElideRight
- width: Math.max(0, settingsTabs.labelColumnWidth)
- anchors.verticalCenter: extruderCountComboBox.verticalCenter
- }
- ComboBox
- {
- id: extruderCountComboBox
- model: ListModel
- {
- id: extruderCountModel
- Component.onCompleted:
- {
- for(var i = 0; i < manager.definedExtruderCount; i++)
- {
- extruderCountModel.append({text: String(i + 1), value: i});
- }
- }
- }
-
- Connections
- {
- target: manager
- onDefinedExtruderCountChanged:
- {
- extruderCountModel.clear();
- for(var i = 0; i < manager.definedExtruderCount; ++i)
- {
- extruderCountModel.append({text: String(i + 1), value: i});
- }
- }
- }
-
- currentIndex: machineExtruderCountProvider.properties.value - 1
- onActivated:
- {
- manager.setMachineExtruderCount(index + 1);
- }
- }
- }
- }
- }
- }
-
- Row
- {
- spacing: UM.Theme.getSize("default_margin").width
- anchors.left: parent.left
- anchors.right: parent.right
- height: parent.height - y
- Column
- {
- height: parent.height
- width: settingsTabs.columnWidth
- Label
- {
- text: catalog.i18nc("@label", "Start G-code")
- font.bold: true
- }
- Loader
- {
- id: machineStartGcodeField
- sourceComponent: gcodeTextArea
- property int areaWidth: parent.width
- property int areaHeight: parent.height - y
- property string settingKey: "machine_start_gcode"
- property string tooltip: catalog.i18nc("@tooltip", "G-code commands to be executed at the very start.")
- }
- }
-
- Column {
- height: parent.height
- width: settingsTabs.columnWidth
- Label
- {
- text: catalog.i18nc("@label", "End G-code")
- font.bold: true
- }
- Loader
- {
- id: machineEndGcodeField
- sourceComponent: gcodeTextArea
- property int areaWidth: parent.width
- property int areaHeight: parent.height - y
- property string settingKey: "machine_end_gcode"
- property string tooltip: catalog.i18nc("@tooltip", "G-code commands to be executed at the very end.")
- }
- }
- }
- }
+ const m = extrudersModel.getItem(i)
+ append({ name: m.name })
}
+ }
+ }
- onCurrentIndexChanged:
+ Cura.RoundedRectangle
+ {
+ anchors
+ {
+ top: tabBar.bottom
+ topMargin: -UM.Theme.getSize("default_lining").height
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ }
+ cornerSide: Cura.RoundedRectangle.Direction.Down
+ border.color: UM.Theme.getColor("lining")
+ border.width: UM.Theme.getSize("default_lining").width
+ radius: UM.Theme.getSize("default_radius").width
+ color: UM.Theme.getColor("main_background")
+ StackLayout
+ {
+ id: tabStack
+ anchors.fill: parent
+
+ currentIndex: tabBar.currentIndex
+
+ MachineSettingsPrinterTab
{
- if(currentIndex > 0)
- {
- contentItem.forceActiveFocus();
- }
+ id: printerTab
}
Repeater
{
- id: extruderTabsRepeater
- model: base.extruderTabsCount
-
- Tab
+ model: extrudersModel
+ delegate: MachineSettingsExtruderTab
{
- title: base.extrudersModel.getItem(index).name
- anchors.margins: UM.Theme.getSize("default_margin").width
-
- Column
- {
- spacing: UM.Theme.getSize("default_lining").width
-
- Label
- {
- text: catalog.i18nc("@label", "Nozzle Settings")
- font.bold: true
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Loader
- {
- id: extruderNozzleSizeField
- visible: !Cura.MachineManager.hasVariants
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_nozzle_size"
- property string label: catalog.i18nc("@label", "Nozzle size")
- property string unit: catalog.i18nc("@label", "mm")
- function afterOnEditingFinished()
- {
- // Somehow the machine_nozzle_size dependent settings are not updated otherwise
- Cura.MachineManager.forceUpdateAllSettings()
- }
- property bool isExtruderSetting: true
- }
-
- Loader
- {
- id: materialDiameterField
- visible: Cura.MachineManager.hasMaterials
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "material_diameter"
- property string label: catalog.i18nc("@label", "Compatible material diameter")
- property string unit: catalog.i18nc("@label", "mm")
- property string tooltip: catalog.i18nc("@tooltip", "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile.")
- function afterOnEditingFinished()
- {
- if (settingsTabs.currentIndex > 0)
- {
- manager.updateMaterialForDiameter(settingsTabs.currentIndex - 1)
- }
- }
- function setValueFunction(value)
- {
- if (settingsTabs.currentIndex > 0)
- {
- const extruderIndex = index.toString()
- Cura.MachineManager.activeMachine.extruders[extruderIndex].compatibleMaterialDiameter = value
- }
- }
- property bool isExtruderSetting: true
- }
-
- Loader
- {
- id: extruderOffsetXField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_nozzle_offset_x"
- property string label: catalog.i18nc("@label", "Nozzle offset X")
- property string unit: catalog.i18nc("@label", "mm")
- property bool isExtruderSetting: true
- property bool forceUpdateOnChange: true
- property bool allowNegative: true
- }
-
- Loader
- {
- id: extruderOffsetYField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_nozzle_offset_y"
- property string label: catalog.i18nc("@label", "Nozzle offset Y")
- property string unit: catalog.i18nc("@label", "mm")
- property bool isExtruderSetting: true
- property bool forceUpdateOnChange: true
- property bool allowNegative: true
- }
-
- Loader
- {
- id: extruderCoolingFanNumberField
- sourceComponent: numericTextFieldWithUnit
- property string settingKey: "machine_extruder_cooling_fan_number"
- property string label: catalog.i18nc("@label", "Cooling Fan Number")
- property string unit: catalog.i18nc("@label", "")
- property bool isExtruderSetting: true
- property bool forceUpdateOnChange: true
- property bool allowNegative: false
- }
-
- Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
-
- Row
- {
- spacing: UM.Theme.getSize("default_margin").width
- anchors.left: parent.left
- anchors.right: parent.right
- height: parent.height - y
- Column
- {
- height: parent.height
- width: settingsTabs.columnWidth
- Label
- {
- text: catalog.i18nc("@label", "Extruder Start G-code")
- font.bold: true
- }
- Loader
- {
- id: extruderStartGcodeField
- sourceComponent: gcodeTextArea
- property int areaWidth: parent.width
- property int areaHeight: parent.height - y
- property string settingKey: "machine_extruder_start_code"
- property bool isExtruderSetting: true
- }
- }
- Column {
- height: parent.height
- width: settingsTabs.columnWidth
- Label
- {
- text: catalog.i18nc("@label", "Extruder End G-code")
- font.bold: true
- }
- Loader
- {
- id: extruderEndGcodeField
- sourceComponent: gcodeTextArea
- property int areaWidth: parent.width
- property int areaHeight: parent.height - y
- property string settingKey: "machine_extruder_end_code"
- property bool isExtruderSetting: true
- }
- }
- }
- }
+ id: discoverTab
+ extruderPosition: model.index
+ extruderStackId: model.id
}
}
}
}
- Component
+ Label
{
- id: simpleCheckBox
- UM.TooltipArea
+ id: machineNameLabel
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+ text: Cura.MachineManager.activeMachine.name
+ horizontalAlignment: Text.AlignHCenter
+ font: UM.Theme.getFont("large_bold")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
+ }
+
+ UM.TabRow
+ {
+ id: tabBar
+ anchors.top: machineNameLabel.bottom
+ anchors.topMargin: UM.Theme.getSize("default_margin").height
+ width: parent.width
+ Repeater
{
- height: checkBox.height
- width: checkBox.width
- text: _tooltip
-
- property bool _isExtruderSetting: (typeof(isExtruderSetting) === 'undefined') ? false: isExtruderSetting
- property bool _forceUpdateOnChange: (typeof(forceUpdateOnChange) === 'undefined') ? false: forceUpdateOnChange
- property string _tooltip: (typeof(tooltip) === 'undefined') ? propertyProvider.properties.description : tooltip
-
- UM.SettingPropertyProvider
+ model: tabNameModel
+ delegate: UM.TabRowButton
{
- id: propertyProvider
-
- containerStackId: {
- if(_isExtruderSetting)
- {
- if(settingsTabs.currentIndex > 0)
- {
- return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
- }
- return "";
- }
- return base.activeMachineId
- }
- key: settingKey
- watchedProperties: [ "value", "description" ]
- storeIndex: manager.containerIndex
- }
-
- CheckBox
- {
- id: checkBox
- text: label
- checked: String(propertyProvider.properties.value).toLowerCase() != 'false'
- onClicked:
- {
- propertyProvider.setPropertyValue("value", checked);
- if(_forceUpdateOnChange)
- {
- manager.forceUpdate();
- }
- }
+ text: model.name
}
}
}
-
- Component
- {
- id: numericTextFieldWithUnit
- UM.TooltipArea
- {
- height: childrenRect.height
- width: childrenRect.width
- text: _tooltip
-
- property bool _isExtruderSetting: (typeof(isExtruderSetting) === 'undefined') ? false: isExtruderSetting
- property bool _allowNegative: (typeof(allowNegative) === 'undefined') ? false : allowNegative
- property var _afterOnEditingFinished: (typeof(afterOnEditingFinished) === 'undefined') ? undefined : afterOnEditingFinished
- property bool _forceUpdateOnChange: (typeof(forceUpdateOnChange) === 'undefined') ? false : forceUpdateOnChange
- property string _label: (typeof(label) === 'undefined') ? "" : label
- property string _tooltip: (typeof(tooltip) === 'undefined') ? propertyProvider.properties.description : tooltip
- property var _setValueFunction: (typeof(setValueFunction) === 'undefined') ? undefined : setValueFunction
-
- UM.SettingPropertyProvider
- {
- id: propertyProvider
-
- containerStackId: {
- if(_isExtruderSetting)
- {
- if(settingsTabs.currentIndex > 0)
- {
- return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
- }
- return "";
- }
- return base.activeMachineId
- }
- key: settingKey
- watchedProperties: [ "value", "description" ]
- storeIndex: manager.containerIndex
- }
-
- Row
- {
- spacing: UM.Theme.getSize("default_margin").width
-
- Label
- {
- text: _label
- visible: _label != ""
- elide: Text.ElideRight
- width: Math.max(0, settingsTabs.labelColumnWidth)
- anchors.verticalCenter: textFieldWithUnit.verticalCenter
- }
-
- Item
- {
- width: textField.width
- height: textField.height
-
- id: textFieldWithUnit
- TextField
- {
- id: textField
- text: {
- const value = propertyProvider.properties.value;
- return value ? value : "";
- }
- validator: RegExpValidator { regExp: _allowNegative ? /-?[0-9\.,]{0,6}/ : /[0-9\.,]{0,6}/ }
- onEditingFinished:
- {
- if (propertyProvider && text != propertyProvider.properties.value)
- {
- // For some properties like the extruder-compatible material diameter, they need to
- // trigger many updates, such as the available materials, the current material may
- // need to be switched, etc. Although setting the diameter can be done directly via
- // the provider, all the updates that need to be triggered then need to depend on
- // the metadata update, a signal that can be fired way too often. The update functions
- // can have if-checks to filter out the irrelevant updates, but still it incurs unnecessary
- // overhead.
- // The ExtruderStack class has a dedicated function for this call "setCompatibleMaterialDiameter()",
- // and it triggers the diameter update signals only when it is needed. Here it is optionally
- // choose to use setCompatibleMaterialDiameter() or other more specific functions that
- // are available.
- if (_setValueFunction !== undefined)
- {
- _setValueFunction(text)
- }
- else
- {
- propertyProvider.setPropertyValue("value", text)
- }
- if(_forceUpdateOnChange)
- {
- manager.forceUpdate()
- }
- if(_afterOnEditingFinished)
- {
- _afterOnEditingFinished()
- }
- }
- }
- }
-
- Label
- {
- text: unit
- anchors.right: textField.right
- anchors.rightMargin: y - textField.y
- anchors.verticalCenter: textField.verticalCenter
- }
- }
- }
- }
- }
-
- Component
- {
- id: comboBoxWithOptions
- UM.TooltipArea
- {
- height: childrenRect.height
- width: childrenRect.width
- text: _tooltip
-
- property bool _isExtruderSetting: (typeof(isExtruderSetting) === 'undefined') ? false : isExtruderSetting
- property bool _forceUpdateOnChange: (typeof(forceUpdateOnChange) === 'undefined') ? false : forceUpdateOnChange
- property var _afterOnActivate: (typeof(afterOnActivate) === 'undefined') ? undefined : afterOnActivate
- property string _label: (typeof(label) === 'undefined') ? "" : label
- property string _tooltip: (typeof(tooltip) === 'undefined') ? propertyProvider.properties.description : tooltip
-
- UM.SettingPropertyProvider
- {
- id: propertyProvider
-
- containerStackId: {
- if(_isExtruderSetting)
- {
- if(settingsTabs.currentIndex > 0)
- {
- return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
- }
- return "";
- }
- return base.activeMachineId
- }
- key: settingKey
- watchedProperties: [ "value", "options", "description" ]
- storeIndex: manager.containerIndex
- }
-
- Row
- {
- spacing: UM.Theme.getSize("default_margin").width
-
- Label
- {
- text: _label
- visible: _label != ""
- elide: Text.ElideRight
- width: Math.max(0, settingsTabs.labelColumnWidth)
- anchors.verticalCenter: comboBox.verticalCenter
- }
- ComboBox
- {
- id: comboBox
- model: ListModel
- {
- id: optionsModel
- Component.onCompleted:
- {
- // Options come in as a string-representation of an OrderedDict
- var options = propertyProvider.properties.options.match(/^OrderedDict\(\[\((.*)\)\]\)$/);
- if(options)
- {
- options = options[1].split("), (")
- for(var i = 0; i < options.length; i++)
- {
- var option = options[i].substring(1, options[i].length - 1).split("', '")
- optionsModel.append({text: option[1], value: option[0]});
- }
- }
- }
- }
- currentIndex:
- {
- var currentValue = propertyProvider.properties.value;
- var index = 0;
- for(var i = 0; i < optionsModel.count; i++)
- {
- if(optionsModel.get(i).value == currentValue) {
- index = i;
- break;
- }
- }
- return index
- }
- onActivated:
- {
- if(propertyProvider.properties.value != optionsModel.get(index).value)
- {
- propertyProvider.setPropertyValue("value", optionsModel.get(index).value);
- if(_forceUpdateOnChange)
- {
- manager.forceUpdate();
- }
- if(_afterOnActivate)
- {
- _afterOnActivate();
- }
- }
- }
- }
- }
- }
- }
-
- Component
- {
- id: gcodeTextArea
-
- UM.TooltipArea
- {
- height: gcodeArea.height
- width: gcodeArea.width
- text: _tooltip
-
- property bool _isExtruderSetting: (typeof(isExtruderSetting) === 'undefined') ? false : isExtruderSetting
- property string _tooltip: (typeof(tooltip) === 'undefined') ? propertyProvider.properties.description : tooltip
-
- UM.SettingPropertyProvider
- {
- id: propertyProvider
-
- containerStackId: {
- if(_isExtruderSetting)
- {
- if(settingsTabs.currentIndex > 0)
- {
- return Cura.ExtruderManager.extruderIds[String(settingsTabs.currentIndex - 1)];
- }
- return "";
- }
- return base.activeMachineId
- }
- key: settingKey
- watchedProperties: [ "value", "description" ]
- storeIndex: manager.containerIndex
- }
-
- TextArea
- {
- id: gcodeArea
- width: areaWidth
- height: areaHeight
- font: UM.Theme.getFont("fixed")
- text: (propertyProvider.properties.value) ? propertyProvider.properties.value : ""
- onActiveFocusChanged:
- {
- if(!activeFocus)
- {
- propertyProvider.setPropertyValue("value", gcodeArea.text)
- }
- }
- Component.onCompleted:
- {
- wrapMode = TextEdit.NoWrap;
- }
- }
- }
- }
-
- Component
- {
- id: headPolygonTextField
- UM.TooltipArea
- {
- height: textField.height
- width: textField.width
- text: tooltip
-
- property string _label: (typeof(label) === 'undefined') ? "" : label
-
- Row
- {
- spacing: UM.Theme.getSize("default_margin").width
-
- Label
- {
- text: _label
- visible: _label != ""
- elide: Text.ElideRight
- width: Math.max(0, settingsTabs.labelColumnWidth)
- anchors.verticalCenter: textFieldWithUnit.verticalCenter
- }
-
- Item
- {
- id: textFieldWithUnit
- width: textField.width
- height: textField.height
-
- TextField
- {
- id: textField
- text:
- {
- var polygon = JSON.parse(machineHeadPolygonProvider.properties.value);
- var item = (axis == "x") ? 0 : 1
- var result = polygon[0][item];
- for(var i = 1; i < polygon.length; i++) {
- if (side == "min") {
- result = Math.min(result, polygon[i][item]);
- } else {
- result = Math.max(result, polygon[i][item]);
- }
- }
- result = Math.abs(result);
- printHeadPolygon[axis][side] = result;
- return result;
- }
- validator: RegExpValidator { regExp: /[0-9\.,]{0,6}/ }
- onEditingFinished:
- {
- printHeadPolygon[axis][side] = parseFloat(textField.text.replace(',','.'));
- var polygon = [];
- polygon.push([-printHeadPolygon["x"]["min"], printHeadPolygon["y"]["max"]]);
- polygon.push([-printHeadPolygon["x"]["min"],-printHeadPolygon["y"]["min"]]);
- polygon.push([ printHeadPolygon["x"]["max"], printHeadPolygon["y"]["max"]]);
- polygon.push([ printHeadPolygon["x"]["max"],-printHeadPolygon["y"]["min"]]);
- var polygon_string = JSON.stringify(polygon);
- if(polygon_string != machineHeadPolygonProvider.properties.value)
- {
- machineHeadPolygonProvider.setPropertyValue("value", polygon_string);
- manager.forceUpdate();
- }
- }
- }
-
- Label
- {
- text: catalog.i18nc("@label", "mm")
- anchors.right: textField.right
- anchors.rightMargin: y - textField.y
- anchors.verticalCenter: textField.verticalCenter
- }
- }
- }
- }
- }
-
- property var printHeadPolygon:
- {
- "x": {
- "min": 0,
- "max": 0,
- },
- "y": {
- "min": 0,
- "max": 0,
- },
- }
-
-
- UM.SettingPropertyProvider
- {
- id: machineExtruderCountProvider
-
- containerStackId: base.activeMachineId
- key: "machine_extruder_count"
- watchedProperties: [ "value", "description" ]
- storeIndex: manager.containerIndex
- }
-
- UM.SettingPropertyProvider
- {
- id: machineHeadPolygonProvider
-
- containerStackId: base.activeMachineId
- key: "machine_head_with_fans_polygon"
- watchedProperties: [ "value" ]
- storeIndex: manager.containerIndex
- }
}
diff --git a/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml b/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml
new file mode 100644
index 0000000000..2ceabf87d0
--- /dev/null
+++ b/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml
@@ -0,0 +1,182 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// This component contains the content for the "Welcome" page of the welcome on-boarding process.
+//
+Item
+{
+ id: base
+ UM.I18nCatalog { id: catalog; name: "cura" }
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+
+ property int labelWidth: 210 * screenScaleFactor
+ property int controlWidth: (UM.Theme.getSize("setting_control").width * 3 / 4) | 0
+ property var labelFont: UM.Theme.getFont("default")
+
+ property int columnWidth: ((parent.width - 2 * UM.Theme.getSize("default_margin").width) / 2) | 0
+ property int columnSpacing: 3 * screenScaleFactor
+ property int propertyStoreIndex: manager ? manager.storeContainerIndex : 1 // definition_changes
+
+ property string extruderStackId: ""
+ property int extruderPosition: 0
+ property var forceUpdateFunction: manager.forceUpdate
+
+ function updateMaterialDiameter()
+ {
+ manager.updateMaterialForDiameter(extruderPosition)
+ }
+
+ Item
+ {
+ id: upperBlock
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: UM.Theme.getSize("default_margin").width
+
+ height: childrenRect.height
+
+ // =======================================
+ // Left-side column "Nozzle Settings"
+ // =======================================
+ Column
+ {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ width: parent.width * 2 / 3
+
+ spacing: base.columnSpacing
+
+ Label // Title Label
+ {
+ text: catalog.i18nc("@title:label", "Nozzle Settings")
+ font: UM.Theme.getFont("medium_bold")
+ renderType: Text.NativeRendering
+ }
+
+ Cura.NumericTextFieldWithUnit // "Nozzle size"
+ {
+ id: extruderNozzleSizeField
+ visible: !Cura.MachineManager.activeMachine.hasVariants
+ containerStackId: base.extruderStackId
+ settingKey: "machine_nozzle_size"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Nozzle size")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.NumericTextFieldWithUnit // "Compatible material diameter"
+ {
+ id: extruderCompatibleMaterialDiameterField
+ containerStackId: base.extruderStackId
+ settingKey: "material_diameter"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Compatible material diameter")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ // Other modules won't automatically respond after the user changes the value, so we need to force it.
+ afterOnEditingFinishedFunction: updateMaterialDiameter
+ }
+
+ Cura.NumericTextFieldWithUnit // "Nozzle offset X"
+ {
+ id: extruderNozzleOffsetXField
+ containerStackId: base.extruderStackId
+ settingKey: "machine_nozzle_offset_x"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Nozzle offset X")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ allowNegativeValue: true
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.NumericTextFieldWithUnit // "Nozzle offset Y"
+ {
+ id: extruderNozzleOffsetYField
+ containerStackId: base.extruderStackId
+ settingKey: "machine_nozzle_offset_y"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Nozzle offset Y")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ allowNegativeValue: true
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.NumericTextFieldWithUnit // "Cooling Fan Number"
+ {
+ id: extruderNozzleCoolingFanNumberField
+ containerStackId: base.extruderStackId
+ settingKey: "machine_extruder_cooling_fan_number"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Cooling Fan Number")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: ""
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+ }
+ }
+
+ Item // Extruder Start and End G-code
+ {
+ id: lowerBlock
+ anchors.top: upperBlock.bottom
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: UM.Theme.getSize("default_margin").width
+
+ Cura.GcodeTextArea // "Extruder Start G-code"
+ {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+ anchors.left: parent.left
+ width: base.columnWidth - UM.Theme.getSize("default_margin").width
+
+ labelText: catalog.i18nc("@title:label", "Extruder Start G-code")
+ containerStackId: base.extruderStackId
+ settingKey: "machine_extruder_start_code"
+ settingStoreIndex: propertyStoreIndex
+ }
+
+ Cura.GcodeTextArea // "Extruder End G-code"
+ {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+ anchors.right: parent.right
+ width: base.columnWidth - UM.Theme.getSize("default_margin").width
+
+ labelText: catalog.i18nc("@title:label", "Extruder End G-code")
+ containerStackId: base.extruderStackId
+ settingKey: "machine_extruder_end_code"
+ settingStoreIndex: propertyStoreIndex
+ }
+ }
+}
diff --git a/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml b/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml
new file mode 100644
index 0000000000..3780d6447b
--- /dev/null
+++ b/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml
@@ -0,0 +1,384 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// This the content in the "Printer" tab in the Machine Settings dialog.
+//
+Item
+{
+ id: base
+ UM.I18nCatalog { id: catalog; name: "cura" }
+
+ property int columnWidth: ((parent.width - 2 * UM.Theme.getSize("default_margin").width) / 2) | 0
+ property int columnSpacing: 3 * screenScaleFactor
+ property int propertyStoreIndex: manager ? manager.storeContainerIndex : 1 // definition_changes
+
+ property int labelWidth: (columnWidth * 2 / 3 - UM.Theme.getSize("default_margin").width * 2) | 0
+ property int controlWidth: (columnWidth / 3) | 0
+ property var labelFont: UM.Theme.getFont("default")
+
+ property string machineStackId: Cura.MachineManager.activeMachine.id
+
+ property var forceUpdateFunction: manager.forceUpdate
+
+ RowLayout
+ {
+ id: upperBlock
+ anchors
+ {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ margins: UM.Theme.getSize("default_margin").width
+ }
+ spacing: UM.Theme.getSize("default_margin").width
+
+ // =======================================
+ // Left-side column for "Printer Settings"
+ // =======================================
+ Column
+ {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignTop
+
+ spacing: base.columnSpacing
+
+ Label // Title Label
+ {
+ text: catalog.i18nc("@title:label", "Printer Settings")
+ font: UM.Theme.getFont("medium_bold")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
+ width: parent.width
+ elide: Text.ElideRight
+ }
+
+ Cura.NumericTextFieldWithUnit // "X (Width)"
+ {
+ id: machineXWidthField
+ containerStackId: machineStackId
+ settingKey: "machine_width"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "X (Width)")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.NumericTextFieldWithUnit // "Y (Depth)"
+ {
+ id: machineYDepthField
+ containerStackId: machineStackId
+ settingKey: "machine_depth"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Y (Depth)")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.NumericTextFieldWithUnit // "Z (Height)"
+ {
+ id: machineZHeightField
+ containerStackId: machineStackId
+ settingKey: "machine_height"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Z (Height)")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.ComboBoxWithOptions // "Build plate shape"
+ {
+ id: buildPlateShapeComboBox
+ containerStackId: machineStackId
+ settingKey: "machine_shape"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Build plate shape")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.SimpleCheckBox // "Origin at center"
+ {
+ id: originAtCenterCheckBox
+ containerStackId: machineStackId
+ settingKey: "machine_center_is_zero"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Origin at center")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.SimpleCheckBox // "Heated bed"
+ {
+ id: heatedBedCheckBox
+ containerStackId: machineStackId
+ settingKey: "machine_heated_bed"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Heated bed")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.SimpleCheckBox // "Heated build volume"
+ {
+ id: heatedVolumeCheckBox
+ containerStackId: machineStackId
+ settingKey: "machine_heated_build_volume"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Heated build volume")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.ComboBoxWithOptions // "G-code flavor"
+ {
+ id: gcodeFlavorComboBox
+ containerStackId: machineStackId
+ settingKey: "machine_gcode_flavor"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "G-code flavor")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ // FIXME(Lipu): better document this.
+ // This has something to do with UM2 and UM2+ regarding "has_material" and the gcode flavor settings.
+ // I don't remember exactly what.
+ afterOnEditingFinishedFunction: manager.updateHasMaterialsMetadata
+ }
+ }
+
+ // =======================================
+ // Right-side column for "Printhead Settings"
+ // =======================================
+ Column
+ {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignTop
+
+ spacing: base.columnSpacing
+
+ Label // Title Label
+ {
+ text: catalog.i18nc("@title:label", "Printhead Settings")
+ font: UM.Theme.getFont("medium_bold")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
+ width: parent.width
+ elide: Text.ElideRight
+ }
+
+ Cura.PrintHeadMinMaxTextField // "X min"
+ {
+ id: machineXMinField
+
+ settingStoreIndex: propertyStoreIndex
+
+ labelText: catalog.i18nc("@label", "X min")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+
+ axisName: "x"
+ axisMinOrMax: "min"
+ allowNegativeValue: true
+ allowPositiveValue: false
+
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.PrintHeadMinMaxTextField // "Y min"
+ {
+ id: machineYMinField
+
+ settingStoreIndex: propertyStoreIndex
+
+ labelText: catalog.i18nc("@label", "Y min")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+
+ axisName: "y"
+ axisMinOrMax: "min"
+ allowNegativeValue: true
+ allowPositiveValue: false
+
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.PrintHeadMinMaxTextField // "X max"
+ {
+ id: machineXMaxField
+
+ settingStoreIndex: propertyStoreIndex
+
+ labelText: catalog.i18nc("@label", "X max")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+
+ axisName: "x"
+ axisMinOrMax: "max"
+ allowNegativeValue: false
+ allowPositiveValue: true
+
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.PrintHeadMinMaxTextField // "Y max"
+ {
+ id: machineYMaxField
+
+ containerStackId: machineStackId
+ settingKey: "machine_head_with_fans_polygon"
+ settingStoreIndex: propertyStoreIndex
+
+ labelText: catalog.i18nc("@label", "Y max")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+
+ axisName: "y"
+ axisMinOrMax: "max"
+ allowNegativeValue: false
+ allowPositiveValue: true
+
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.NumericTextFieldWithUnit // "Gantry Height"
+ {
+ id: machineGantryHeightField
+ containerStackId: machineStackId
+ settingKey: "gantry_height"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Gantry Height")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ unitText: catalog.i18nc("@label", "mm")
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+
+ Cura.ComboBoxWithOptions // "Number of Extruders"
+ {
+ id: numberOfExtrudersComboBox
+ containerStackId: machineStackId
+ settingKey: "machine_extruder_count"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Number of Extruders")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ controlWidth: base.controlWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ // FIXME(Lipu): better document this.
+ // This has something to do with UM2 and UM2+ regarding "has_material" and the gcode flavor settings.
+ // I don't remember exactly what.
+ afterOnEditingFinishedFunction: manager.updateHasMaterialsMetadata
+ setValueFunction: manager.setMachineExtruderCount
+
+ optionModel: ListModel
+ {
+ id: extruderCountModel
+
+ Component.onCompleted:
+ {
+ update()
+ }
+
+ function update()
+ {
+ clear()
+ for (var i = 1; i <= Cura.MachineManager.activeMachine.maxExtruderCount; i++)
+ {
+ // Use String as value. JavaScript only has Number. PropertyProvider.setPropertyValue()
+ // takes a QVariant as value, and Number gets translated into a float. This will cause problem
+ // for integer settings such as "Number of Extruders".
+ append({ text: String(i), value: String(i) })
+ }
+ }
+ }
+
+ Connections
+ {
+ target: Cura.MachineManager
+ onGlobalContainerChanged: extruderCountModel.update()
+ }
+ }
+
+ Cura.SimpleCheckBox // "Shared Heater"
+ {
+ id: sharedHeaterCheckBox
+ containerStackId: machineStackId
+ settingKey: "machine_extruders_share_heater"
+ settingStoreIndex: propertyStoreIndex
+ labelText: catalog.i18nc("@label", "Shared Heater")
+ labelFont: base.labelFont
+ labelWidth: base.labelWidth
+ forceUpdateOnChangeFunction: forceUpdateFunction
+ }
+ }
+ }
+
+ RowLayout // Start and End G-code
+ {
+ id: lowerBlock
+ spacing: UM.Theme.getSize("default_margin").width
+ anchors
+ {
+ top: upperBlock.bottom
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ margins: UM.Theme.getSize("default_margin").width
+ }
+
+ Cura.GcodeTextArea // "Start G-code"
+ {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ labelText: catalog.i18nc("@title:label", "Start G-code")
+ containerStackId: machineStackId
+ settingKey: "machine_start_gcode"
+ settingStoreIndex: propertyStoreIndex
+ }
+
+ Cura.GcodeTextArea // "End G-code"
+ {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ labelText: catalog.i18nc("@title:label", "End G-code")
+ containerStackId: machineStackId
+ settingKey: "machine_end_gcode"
+ settingStoreIndex: propertyStoreIndex
+ }
+ }
+}
diff --git a/plugins/MachineSettingsAction/plugin.json b/plugins/MachineSettingsAction/plugin.json
index d734c1adf5..cc1e5fb01e 100644
--- a/plugins/MachineSettingsAction/plugin.json
+++ b/plugins/MachineSettingsAction/plugin.json
@@ -3,6 +3,6 @@
"author": "fieldOfView",
"version": "1.0.1",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/ModelChecker/ModelChecker.py b/plugins/ModelChecker/ModelChecker.py
index 0619c95d67..0afed28f19 100644
--- a/plugins/ModelChecker/ModelChecker.py
+++ b/plugins/ModelChecker/ModelChecker.py
@@ -76,7 +76,9 @@ class ModelChecker(QObject, Extension):
# This function can be triggered in the middle of a machine change, so do not proceed if the machine change
# has not done yet.
- if str(node_extruder_position) not in global_container_stack.extruders:
+ try:
+ extruder = global_container_stack.extruderList[int(node_extruder_position)]
+ except IndexError:
Application.getInstance().callLater(lambda: self.onChanged.emit())
return False
@@ -131,9 +133,9 @@ class ModelChecker(QObject, Extension):
material_shrinkage = {}
# Get all shrinkage values of materials used
- for extruder_position, extruder in global_container_stack.extruders.items():
+ for extruder_position, extruder in enumerate(global_container_stack.extruderList):
shrinkage = extruder.material.getProperty("material_shrinkage_percentage", "value")
if shrinkage is None:
shrinkage = 0
- material_shrinkage[extruder_position] = shrinkage
+ material_shrinkage[str(extruder_position)] = shrinkage
return material_shrinkage
diff --git a/plugins/ModelChecker/plugin.json b/plugins/ModelChecker/plugin.json
index 59be5bbf0a..6437fb0802 100644
--- a/plugins/ModelChecker/plugin.json
+++ b/plugins/ModelChecker/plugin.json
@@ -2,7 +2,7 @@
"name": "Model Checker",
"author": "Ultimaker B.V.",
"version": "1.0.1",
- "api": "6.0",
+ "api": "7.0",
"description": "Checks models and print configuration for possible printing issues and give suggestions.",
"i18n-catalog": "cura"
}
diff --git a/plugins/MonitorStage/MonitorMain.qml b/plugins/MonitorStage/MonitorMain.qml
index 88193737bb..a70c10ff0f 100644
--- a/plugins/MonitorStage/MonitorMain.qml
+++ b/plugins/MonitorStage/MonitorMain.qml
@@ -12,12 +12,20 @@ Rectangle
id: viewportOverlay
property bool isConnected: Cura.MachineManager.activeMachineHasNetworkConnection || Cura.MachineManager.activeMachineHasCloudConnection
- property bool isNetworkConfigurable: ["Ultimaker 3", "Ultimaker 3 Extended", "Ultimaker S5"].indexOf(Cura.MachineManager.activeMachineDefinitionName) > -1
+ property bool isNetworkConfigurable:
+ {
+ if(Cura.MachineManager.activeMachine === null)
+ {
+ return false
+ }
+ return Cura.MachineManager.activeMachine.supportsNetworkConnection
+ }
+
property bool isNetworkConfigured:
{
// Readability:
var connectedTypes = [2, 3];
- var types = Cura.MachineManager.activeMachineConfiguredConnectionTypes
+ var types = Cura.MachineManager.activeMachine.configuredConnectionTypes
// Check if configured connection types includes either 2 or 3 (LAN or cloud)
for (var i = 0; i < types.length; i++)
@@ -89,7 +97,7 @@ Rectangle
horizontalCenter: parent.horizontalCenter
}
visible: isNetworkConfigured && !isConnected
- text: catalog.i18nc("@info", "Please make sure your printer has a connection:\n- Check if the printer is turned on.\n- Check if the printer is connected to the network.")
+ text: catalog.i18nc("@info", "Please make sure your printer has a connection:\n- Check if the printer is turned on.\n- Check if the printer is connected to the network.\n- Check if you are signed in to discover cloud-connected printers.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("monitor_text_primary")
wrapMode: Text.WordWrap
@@ -98,7 +106,6 @@ Rectangle
width: contentWidth
}
- // CASE 3: CAN NOT MONITOR
Label
{
id: noNetworkLabel
@@ -106,24 +113,8 @@ Rectangle
{
horizontalCenter: parent.horizontalCenter
}
- visible: !isNetworkConfigured
- text: catalog.i18nc("@info", "Please select a network connected printer to monitor.")
- font: UM.Theme.getFont("medium")
- color: UM.Theme.getColor("monitor_text_primary")
- wrapMode: Text.WordWrap
- width: contentWidth
- lineHeight: UM.Theme.getSize("monitor_text_line_large").height
- lineHeightMode: Text.FixedHeight
- }
- Label
- {
- id: noNetworkUltimakerLabel
- anchors
- {
- horizontalCenter: parent.horizontalCenter
- }
visible: !isNetworkConfigured && isNetworkConfigurable
- text: catalog.i18nc("@info", "Please connect your Ultimaker printer to your local network.")
+ text: catalog.i18nc("@info", "Please connect your printer to the network.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("monitor_text_primary")
wrapMode: Text.WordWrap
@@ -135,7 +126,7 @@ Rectangle
{
anchors
{
- left: noNetworkUltimakerLabel.left
+ left: noNetworkLabel.left
}
visible: !isNetworkConfigured && isNetworkConfigurable
height: UM.Theme.getSize("monitor_text_line").height
@@ -160,7 +151,7 @@ Rectangle
verticalCenter: externalLinkIcon.verticalCenter
}
color: UM.Theme.getColor("monitor_text_link")
- font: UM.Theme.getFont("medium") // 14pt, regular
+ font: UM.Theme.getFont("medium")
linkColor: UM.Theme.getColor("monitor_text_link")
text: catalog.i18nc("@label link to technical assistance", "View user manuals online")
renderType: Text.NativeRendering
@@ -170,15 +161,9 @@ Rectangle
anchors.fill: parent
hoverEnabled: true
onClicked: Qt.openUrlExternally("https://ultimaker.com/en/resources/manuals/ultimaker-3d-printers")
- onEntered:
- {
- manageQueueText.font.underline = true
- }
- onExited:
- {
- manageQueueText.font.underline = false
- }
+ onEntered: manageQueueText.font.underline = true
+ onExited: manageQueueText.font.underline = false
}
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/MonitorStage/MonitorStage.py b/plugins/MonitorStage/MonitorStage.py
index 69b7f20f4e..3d2a1c3f37 100644
--- a/plugins/MonitorStage/MonitorStage.py
+++ b/plugins/MonitorStage/MonitorStage.py
@@ -2,8 +2,6 @@
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
from UM.Application import Application
-from UM.PluginRegistry import PluginRegistry
-from UM.Resources import Resources
from cura.Stages.CuraStage import CuraStage
diff --git a/plugins/MonitorStage/__init__.py b/plugins/MonitorStage/__init__.py
index 0468e6319b..a755268c79 100644
--- a/plugins/MonitorStage/__init__.py
+++ b/plugins/MonitorStage/__init__.py
@@ -12,7 +12,7 @@ def getMetaData():
return {
"stage": {
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
- "weight": 2
+ "weight": 30
}
}
diff --git a/plugins/MonitorStage/plugin.json b/plugins/MonitorStage/plugin.json
index 95e4b86f36..2274351527 100644
--- a/plugins/MonitorStage/plugin.json
+++ b/plugins/MonitorStage/plugin.json
@@ -1,8 +1,8 @@
-{
- "name": "Monitor Stage",
- "author": "Ultimaker B.V.",
- "version": "1.0.1",
- "description": "Provides a monitor stage in Cura.",
- "api": "6.0",
- "i18n-catalog": "cura"
+{
+ "name": "Monitor Stage",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.1",
+ "description": "Provides a monitor stage in Cura.",
+ "api": "7.0",
+ "i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/PerObjectSettingsTool/PerObjectItem.qml b/plugins/PerObjectSettingsTool/PerObjectItem.qml
index 559ad2bf81..7c6ece12db 100644
--- a/plugins/PerObjectSettingsTool/PerObjectItem.qml
+++ b/plugins/PerObjectSettingsTool/PerObjectItem.qml
@@ -29,6 +29,17 @@ UM.TooltipArea
UM.ActiveTool.forceUpdate();
}
}
+
+ // When the user removes settings from the list addedSettingsModel, we need to recheck if the
+ // setting is visible or not to show a mark in the CheckBox.
+ Connections
+ {
+ target: addedSettingsModel
+ onVisibleCountChanged:
+ {
+ check.checked = addedSettingsModel.getVisible(model.key)
+ }
+ }
}
diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py
index 3e1df1c7b8..61d0dbc0f0 100644
--- a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py
+++ b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py
@@ -1,7 +1,7 @@
# Copyright (c) 2016 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
+from PyQt5.QtCore import pyqtProperty
from UM.FlameProfiler import pyqtSlot
from UM.Application import Application
@@ -13,6 +13,7 @@ import UM.Settings.Models.SettingVisibilityHandler
from cura.Settings.ExtruderManager import ExtruderManager #To get global-inherits-stack setting values from different extruders.
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
+
## The per object setting visibility handler ensures that only setting
# definitions that have a matching instance Container are returned as visible.
class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler.SettingVisibilityHandler):
diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
index 0e2bd88619..bb342d5045 100644
--- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
+++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
@@ -4,22 +4,68 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
-import QtQuick.Window 2.2
import UM 1.2 as UM
import Cura 1.0 as Cura
import ".."
-Item {
- id: base;
- UM.I18nCatalog { id: catalog; name: "cura"; }
-
- width: childrenRect.width;
- height: childrenRect.height;
- property var all_categories_except_support: [ "machine_settings", "resolution", "shell", "infill", "material", "speed",
+Item
+{
+ id: base
+ width: childrenRect.width
+ height: childrenRect.height
+ property var allCategoriesExceptSupport: [ "machine_settings", "resolution", "shell", "infill", "material", "speed",
"travel", "cooling", "platform_adhesion", "dual", "meshfix", "blackmagic", "experimental"]
+ readonly property string normalMeshType: ""
+ readonly property string supportMeshType: "support_mesh"
+ readonly property string cuttingMeshType: "cutting_mesh"
+ readonly property string infillMeshType: "infill_mesh"
+ readonly property string antiOverhangMeshType: "anti_overhang_mesh"
+
+ property var currentMeshType: UM.ActiveTool.properties.getValue("MeshType")
+
+ // Update the view every time the currentMeshType changes
+ onCurrentMeshTypeChanged:
+ {
+ var type = currentMeshType
+
+ // set checked state of mesh type buttons
+ normalButton.checked = type === normalMeshType
+ supportMeshButton.checked = type === supportMeshType
+ overhangMeshButton.checked = type === infillMeshType || type === cuttingMeshType
+ antiOverhangMeshButton.checked = type === antiOverhangMeshType
+
+ // update active type label
+ for (var button in meshTypeButtons.children)
+ {
+ if (meshTypeButtons.children[button].checked){
+ meshTypeLabel.text = catalog.i18nc("@label", "Mesh Type") + ": " + meshTypeButtons.children[button].text
+ break
+ }
+ }
+ }
+
+ function setOverhangsMeshType()
+ {
+ if (infillOnlyCheckbox.checked)
+ {
+ setMeshType(infillMeshType)
+ }
+ else
+ {
+ setMeshType(cuttingMeshType)
+ }
+ }
+
+ function setMeshType(type)
+ {
+ UM.ActiveTool.setProperty("MeshType", type)
+ }
+
+ UM.I18nCatalog { id: catalog; name: "uranium"}
+
Column
{
id: items
@@ -28,123 +74,97 @@ Item {
spacing: UM.Theme.getSize("default_margin").height
- Row
+ Row // Mesh type buttons
{
+ id: meshTypeButtons
spacing: UM.Theme.getSize("default_margin").width
- Label
+ Button
{
- text: catalog.i18nc("@label","Mesh Type")
- font: UM.Theme.getFont("default")
- color: UM.Theme.getColor("text")
- height: UM.Theme.getSize("setting").height
- verticalAlignment: Text.AlignVCenter
+ id: normalButton
+ text: catalog.i18nc("@label", "Normal model")
+ iconSource: UM.Theme.getIcon("pos_normal");
+ property bool needBorder: true
+ checkable: true
+ onClicked: setMeshType(normalMeshType);
+ style: UM.Theme.styles.tool_button;
+ z: 4
}
- UM.SettingPropertyProvider
+ Button
{
- id: meshTypePropertyProvider
- containerStack: Cura.MachineManager.activeMachine
- watchedProperties: [ "enabled" ]
+ id: supportMeshButton
+ text: catalog.i18nc("@label", "Print as support")
+ iconSource: UM.Theme.getIcon("pos_print_as_support");
+ property bool needBorder: true
+ checkable:true
+ onClicked: setMeshType(supportMeshType)
+ style: UM.Theme.styles.tool_button;
+ z: 3
}
- ComboBox
+ Button
{
- id: meshTypeSelection
- style: UM.Theme.styles.combobox
- onActivated: {
- UM.ActiveTool.setProperty("MeshType", model.get(index).type)
- }
- model: ListModel
- {
- id: meshTypeModel
- Component.onCompleted: meshTypeSelection.populateModel()
- }
-
- function populateModel()
- {
- meshTypeModel.append({
- type: "",
- text: catalog.i18nc("@label", "Normal model")
- });
- meshTypePropertyProvider.key = "support_mesh";
- if(meshTypePropertyProvider.properties.enabled == "True")
- {
- meshTypeModel.append({
- type: "support_mesh",
- text: catalog.i18nc("@label", "Print as support")
- });
- }
- meshTypePropertyProvider.key = "anti_overhang_mesh";
- if(meshTypePropertyProvider.properties.enabled == "True")
- {
- meshTypeModel.append({
- type: "anti_overhang_mesh",
- text: catalog.i18nc("@label", "Don't support overlap with other models")
- });
- }
- meshTypePropertyProvider.key = "cutting_mesh";
- if(meshTypePropertyProvider.properties.enabled == "True")
- {
- meshTypeModel.append({
- type: "cutting_mesh",
- text: catalog.i18nc("@label", "Modify settings for overlap with other models")
- });
- }
- meshTypePropertyProvider.key = "infill_mesh";
- if(meshTypePropertyProvider.properties.enabled == "True")
- {
- meshTypeModel.append({
- type: "infill_mesh",
- text: catalog.i18nc("@label", "Modify settings for infill of other models")
- });
- }
-
- meshTypeSelection.updateCurrentIndex();
- }
-
- function updateCurrentIndex()
- {
- var mesh_type = UM.ActiveTool.properties.getValue("MeshType");
- meshTypeSelection.currentIndex = -1;
- for(var index=0; index < meshTypeSelection.model.count; index++)
- {
- if(meshTypeSelection.model.get(index).type == mesh_type)
- {
- meshTypeSelection.currentIndex = index;
- return;
- }
- }
- meshTypeSelection.currentIndex = 0;
- }
+ id: overhangMeshButton
+ text: catalog.i18nc("@label", "Modify settings for overlaps")
+ iconSource: UM.Theme.getIcon("pos_modify_overlaps");
+ property bool needBorder: true
+ checkable:true
+ onClicked: setMeshType(infillMeshType)
+ style: UM.Theme.styles.tool_button;
+ z: 2
}
- Connections
+ Button
{
- target: Cura.MachineManager
- onGlobalContainerChanged:
- {
- meshTypeSelection.model.clear();
- meshTypeSelection.populateModel();
- }
- }
-
- Connections
- {
- target: UM.Selection
- onSelectionChanged: meshTypeSelection.updateCurrentIndex()
+ id: antiOverhangMeshButton
+ text: catalog.i18nc("@label", "Don't support overlaps")
+ iconSource: UM.Theme.getIcon("pos_modify_dont_support_overlap");
+ property bool needBorder: true
+ checkable: true
+ onClicked: setMeshType(antiOverhangMeshType)
+ style: UM.Theme.styles.tool_button;
+ z: 1
}
}
- Column
+ Label
+ {
+ id: meshTypeLabel
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ height: UM.Theme.getSize("setting").height
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ CheckBox
+ {
+ id: infillOnlyCheckbox
+
+ text: catalog.i18nc("@action:checkbox", "Infill only");
+
+ style: UM.Theme.styles.checkbox;
+
+ visible: currentMeshType === infillMeshType || currentMeshType === cuttingMeshType
+ onClicked: setOverhangsMeshType()
+
+ Binding
+ {
+ target: infillOnlyCheckbox
+ property: "checked"
+ value: currentMeshType === infillMeshType
+ }
+ }
+
+ Column // Settings Dialog
{
// This is to ensure that the panel is first increasing in size up to 200 and then shows a scrollbar.
// It kinda looks ugly otherwise (big panel, no content on it)
id: currentSettings
property int maximumHeight: 200 * screenScaleFactor
height: Math.min(contents.count * (UM.Theme.getSize("section").height + UM.Theme.getSize("default_lining").height), maximumHeight)
- visible: meshTypeSelection.model.get(meshTypeSelection.currentIndex).type != "anti_overhang_mesh"
+ visible: currentMeshType != "anti_overhang_mesh"
ScrollView
{
@@ -159,26 +179,26 @@ Item {
model: UM.SettingDefinitionsModel
{
- id: addedSettingsModel;
- containerId: Cura.MachineManager.activeDefinitionId
+ id: addedSettingsModel
+ containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
expanded: [ "*" ]
filter:
{
if (printSequencePropertyProvider.properties.value == "one_at_a_time")
{
- return {"settable_per_meshgroup": true};
+ return {"settable_per_meshgroup": true}
}
- return {"settable_per_mesh": true};
+ return {"settable_per_mesh": true}
}
exclude:
{
- var excluded_settings = [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ];
+ var excluded_settings = [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]
- if(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh")
+ if (currentMeshType == "support_mesh")
{
- excluded_settings = excluded_settings.concat(base.all_categories_except_support);
+ excluded_settings = excluded_settings.concat(base.allCategoriesExceptSupport)
}
- return excluded_settings;
+ return excluded_settings
}
visibilityHandler: Cura.PerObjectSettingVisibilityHandler
@@ -188,8 +208,9 @@ Item {
// For some reason the model object is updated after removing him from the memory and
// it happens only on Windows. For this reason, set the destroyed value manually.
- Component.onDestruction: {
- setDestroyed(true);
+ Component.onDestruction:
+ {
+ setDestroyed(true)
}
}
@@ -213,7 +234,8 @@ Item {
//causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
asynchronous: model.type != "enum" && model.type != "extruder"
- onLoaded: {
+ onLoaded:
+ {
settingLoader.item.showRevertButton = false
settingLoader.item.showInheritButton = false
settingLoader.item.showLinkedSettingIcon = false
@@ -299,7 +321,7 @@ Item {
target: inheritStackProvider
onPropertiesChanged:
{
- provider.forcePropertiesChanged();
+ provider.forcePropertiesChanged()
}
}
@@ -312,22 +334,22 @@ Item {
// so here we connect to the signal and update the those values.
if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
{
- const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId");
+ const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId")
if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
{
- addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId;
+ addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId
}
}
if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
{
- const containerId = UM.ActiveTool.properties.getValue("ContainerID");
+ const containerId = UM.ActiveTool.properties.getValue("ContainerID")
if (provider.containerStackId != containerId)
{
- provider.containerStackId = containerId;
+ provider.containerStackId = containerId
}
if (inheritStackProvider.containerStackId != containerId)
{
- inheritStackProvider.containerStackId = containerId;
+ inheritStackProvider.containerStackId = containerId
}
}
}
@@ -337,7 +359,7 @@ Item {
}
}
- Button
+ Cura.SecondaryButton
{
id: customiseSettingsButton;
height: UM.Theme.getSize("setting_control").height;
@@ -345,33 +367,12 @@ Item {
text: catalog.i18nc("@action:button", "Select settings");
- style: ButtonStyle
- {
- background: Rectangle
- {
- width: control.width;
- height: control.height;
- border.width: UM.Theme.getSize("default_lining").width;
- border.color: control.pressed ? UM.Theme.getColor("action_button_active_border") :
- control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
- color: control.pressed ? UM.Theme.getColor("action_button_active") :
- control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
- }
- label: Label
- {
- text: control.text;
- color: UM.Theme.getColor("setting_control_text");
- font: UM.Theme.getFont("default")
- anchors.centerIn: parent
- }
- }
-
onClicked:
{
settingPickDialog.visible = true;
- if (meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh")
+ if (currentMeshType == "support_mesh")
{
- settingPickDialog.additional_excluded_settings = base.all_categories_except_support;
+ settingPickDialog.additional_excluded_settings = base.allCategoriesExceptSupport;
}
else
{
@@ -379,138 +380,12 @@ Item {
}
}
}
+
}
-
- UM.Dialog {
+ SettingPickDialog
+ {
id: settingPickDialog
-
- title: catalog.i18nc("@title:window", "Select Settings to Customize for this model")
- width: screenScaleFactor * 360
-
- property var additional_excluded_settings
-
- onVisibilityChanged:
- {
- // force updating the model to sync it with addedSettingsModel
- if(visible)
- {
- // Set skip setting, it will prevent from resetting selected mesh_type
- contents.model.visibilityHandler.addSkipResetSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type)
- listview.model.forceUpdate()
-
- updateFilter()
- }
- }
-
- function updateFilter()
- {
- var new_filter = {};
- new_filter["settable_per_mesh"] = true;
- // Don't filter on "settable_per_meshgroup" any more when `printSequencePropertyProvider.properties.value`
- // is set to "one_at_a_time", because the current backend architecture isn't ready for that.
-
- if(filterInput.text != "")
- {
- new_filter["i18n_label"] = "*" + filterInput.text;
- }
-
- listview.model.filter = new_filter;
- }
-
- TextField {
- id: filterInput
-
- anchors {
- top: parent.top
- left: parent.left
- right: toggleShowAll.left
- rightMargin: UM.Theme.getSize("default_margin").width
- }
-
- placeholderText: catalog.i18nc("@label:textbox", "Filter...");
-
- onTextChanged: settingPickDialog.updateFilter()
- }
-
- CheckBox
- {
- id: toggleShowAll
-
- anchors {
- top: parent.top
- right: parent.right
- }
-
- text: catalog.i18nc("@label:checkbox", "Show all")
- checked: listview.model.showAll
- onClicked:
- {
- listview.model.showAll = checked;
- }
- }
-
- ScrollView
- {
- id: scrollView
-
- anchors
- {
- top: filterInput.bottom;
- left: parent.left;
- right: parent.right;
- bottom: parent.bottom;
- }
- ListView
- {
- id:listview
- model: UM.SettingDefinitionsModel
- {
- id: definitionsModel;
- containerId: Cura.MachineManager.activeDefinitionId
- visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
- expanded: [ "*" ]
- exclude:
- {
- var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ];
- excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings);
- return excluded_settings;
- }
- }
- delegate:Loader
- {
- id: loader
-
- width: parent.width
- height: model.type != undefined ? UM.Theme.getSize("section").height : 0;
-
- property var definition: model
- property var settingDefinitionsModel: definitionsModel
-
- asynchronous: true
- source:
- {
- switch(model.type)
- {
- case "category":
- return "PerObjectCategory.qml"
- default:
- return "PerObjectItem.qml"
- }
- }
- }
- Component.onCompleted: settingPickDialog.updateFilter()
- }
- }
-
- rightButtons: [
- Button {
- text: catalog.i18nc("@action:button", "Close");
- onClicked: {
- settingPickDialog.visible = false;
- }
- }
- ]
}
UM.SettingPropertyProvider
@@ -533,25 +408,25 @@ Item {
storeIndex: 0
}
- SystemPalette { id: palette; }
+ SystemPalette { id: palette }
Component
{
- id: settingTextField;
+ id: settingTextField
Cura.SettingTextField { }
}
Component
{
- id: settingComboBox;
+ id: settingComboBox
Cura.SettingComboBox { }
}
Component
{
- id: settingExtruder;
+ id: settingExtruder
Cura.SettingExtruder { }
}
@@ -565,22 +440,23 @@ Item {
Component
{
- id: settingCheckBox;
+ id: settingCheckBox
Cura.SettingCheckBox { }
}
Component
{
- id: settingCategory;
+ id: settingCategory
Cura.SettingCategory { }
}
Component
{
- id: settingUnknown;
+ id: settingUnknown
Cura.SettingUnknown { }
}
+
}
diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py
index baa700165c..b2eb925a6d 100644
--- a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py
+++ b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py
@@ -1,6 +1,6 @@
# Copyright (c) 2016 Ultimaker B.V.
# Uranium is released under the terms of the LGPLv3 or higher.
-
+from UM.Logger import Logger
from UM.Tool import Tool
from UM.Scene.Selection import Selection
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@@ -20,15 +20,11 @@ class PerObjectSettingsTool(Tool):
self.setExposedProperties("SelectedObjectId", "ContainerID", "SelectedActiveExtruder", "MeshType")
- self._advanced_mode = False
self._multi_extrusion = False
self._single_model_selected = False
Selection.selectionChanged.connect(self.propertyChanged)
- Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferenceChanged)
- self._onPreferenceChanged("cura/active_mode")
-
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
self._onGlobalContainerChanged()
Selection.selectionChanged.connect(self._updateEnabled)
@@ -70,8 +66,16 @@ class PerObjectSettingsTool(Tool):
selected_object.addDecorator(SettingOverrideDecorator())
selected_object.callDecoration("setActiveExtruder", extruder_stack_id)
- def setMeshType(self, mesh_type):
+ ## Returns True when the mesh_type was changed, False when current mesh_type == mesh_type
+ def setMeshType(self, mesh_type: str) -> bool:
+ if self.getMeshType() == mesh_type:
+ return False
+
selected_object = Selection.getSelectedObject(0)
+ if selected_object is None:
+ Logger.log("w", "Tried setting the mesh type of the selected object, but no object was selected")
+ return False
+
stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
if not stack:
selected_object.addDecorator(SettingOverrideDecorator())
@@ -90,6 +94,9 @@ class PerObjectSettingsTool(Tool):
new_instance.resetState() # Ensure that the state is not seen as a user state.
settings.addInstance(new_instance)
+ self.propertyChanged.emit()
+ return True
+
def getMeshType(self):
selected_object = Selection.getSelectedObject(0)
stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
@@ -103,11 +110,6 @@ class PerObjectSettingsTool(Tool):
return ""
- def _onPreferenceChanged(self, preference):
- if preference == "cura/active_mode":
- self._advanced_mode = Application.getInstance().getPreferences().getValue(preference) == 1
- self._updateEnabled()
-
def _onGlobalContainerChanged(self):
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
@@ -140,4 +142,4 @@ class PerObjectSettingsTool(Tool):
self._single_model_selected = False # Group is selected, so tool needs to be disabled
else:
self._single_model_selected = True
- Application.getInstance().getController().toolEnabledChanged.emit(self._plugin_id, self._advanced_mode and self._single_model_selected)
+ Application.getInstance().getController().toolEnabledChanged.emit(self._plugin_id, self._single_model_selected)
diff --git a/plugins/PerObjectSettingsTool/SettingPickDialog.qml b/plugins/PerObjectSettingsTool/SettingPickDialog.qml
new file mode 100644
index 0000000000..92e22f26bc
--- /dev/null
+++ b/plugins/PerObjectSettingsTool/SettingPickDialog.qml
@@ -0,0 +1,139 @@
+import QtQuick 2.2
+import QtQuick.Controls 1.2
+import QtQuick.Controls.Styles 1.2
+
+import UM 1.2 as UM
+import Cura 1.0 as Cura
+import ".."
+
+UM.Dialog
+ {
+ id: settingPickDialog
+
+ title: catalog.i18nc("@title:window", "Select Settings to Customize for this model")
+ width: screenScaleFactor * 360
+
+ property var additional_excluded_settings
+
+ onVisibilityChanged:
+ {
+ // force updating the model to sync it with addedSettingsModel
+ if (visible)
+ {
+ // Set skip setting, it will prevent from resetting selected mesh_type
+ contents.model.visibilityHandler.addSkipResetSetting(currentMeshType)
+ listview.model.forceUpdate()
+
+ updateFilter()
+ }
+ }
+
+ function updateFilter()
+ {
+ var new_filter = {}
+ new_filter["settable_per_mesh"] = true
+ // Don't filter on "settable_per_meshgroup" any more when `printSequencePropertyProvider.properties.value`
+ // is set to "one_at_a_time", because the current backend architecture isn't ready for that.
+
+ if (filterInput.text != "")
+ {
+ new_filter["i18n_label"] = "*" + filterInput.text
+ }
+
+ listview.model.filter = new_filter
+ }
+
+ TextField {
+ id: filterInput
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: toggleShowAll.left
+ rightMargin: UM.Theme.getSize("default_margin").width
+ }
+
+ placeholderText: catalog.i18nc("@label:textbox", "Filter...")
+
+ onTextChanged: settingPickDialog.updateFilter()
+ }
+
+ CheckBox
+ {
+ id: toggleShowAll
+
+ anchors {
+ top: parent.top
+ right: parent.right
+ }
+
+ text: catalog.i18nc("@label:checkbox", "Show all")
+ checked: listview.model.showAll
+ onClicked:
+ {
+ listview.model.showAll = checked
+ }
+ }
+
+ ScrollView
+ {
+ id: scrollView
+
+ anchors
+ {
+ top: filterInput.bottom
+ left: parent.left
+ right: parent.right
+ bottom: parent.bottom
+ }
+ ListView
+ {
+ id:listview
+ model: UM.SettingDefinitionsModel
+ {
+ id: definitionsModel
+ containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
+ visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
+ expanded: [ "*" ]
+ exclude:
+ {
+ var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]
+ excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings)
+ return excluded_settings
+ }
+ }
+ delegate:Loader
+ {
+ id: loader
+
+ width: parent.width
+ height: model.type != undefined ? UM.Theme.getSize("section").height : 0
+
+ property var definition: model
+ property var settingDefinitionsModel: definitionsModel
+
+ asynchronous: true
+ source:
+ {
+ switch(model.type)
+ {
+ case "category":
+ return "PerObjectCategory.qml"
+ default:
+ return "PerObjectItem.qml"
+ }
+ }
+ }
+ Component.onCompleted: settingPickDialog.updateFilter()
+ }
+ }
+
+ rightButtons: [
+ Button {
+ text: catalog.i18nc("@action:button", "Close")
+ onClicked: {
+ settingPickDialog.visible = false
+ }
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/plugins/PerObjectSettingsTool/plugin.json b/plugins/PerObjectSettingsTool/plugin.json
index f272abf06a..b30acfd52e 100644
--- a/plugins/PerObjectSettingsTool/plugin.json
+++ b/plugins/PerObjectSettingsTool/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides the Per Model Settings.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/PerObjectSettingsTool/tool_icon.svg b/plugins/PerObjectSettingsTool/tool_icon.svg
index 4b15eb453f..41e49cae07 100644
--- a/plugins/PerObjectSettingsTool/tool_icon.svg
+++ b/plugins/PerObjectSettingsTool/tool_icon.svg
@@ -1,3 +1,22 @@
-
+
+
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py
index 78f9cc0516..376ab291c4 100644
--- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py
+++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py
@@ -162,7 +162,7 @@ class PostProcessingPlugin(QObject, Extension):
loaded_script = importlib.util.module_from_spec(spec)
if spec.loader is None:
continue
- spec.loader.exec_module(loaded_script)
+ spec.loader.exec_module(loaded_script) # type: ignore
sys.modules[script_name] = loaded_script #TODO: This could be a security risk. Overwrite any module with a user-provided name?
loaded_class = getattr(loaded_script, script_name)
@@ -219,6 +219,7 @@ class PostProcessingPlugin(QObject, Extension):
self._script_list.clear()
if not new_stack.getMetaDataEntry("post_processing_scripts"): # Missing or empty.
self.scriptListChanged.emit() # Even emit this if it didn't change. We want it to write the empty list to the stack's metadata.
+ self.setSelectedScriptIndex(-1)
return
self._script_list.clear()
diff --git a/plugins/PostProcessingPlugin/plugin.json b/plugins/PostProcessingPlugin/plugin.json
index 1e73133c53..6a2b84933e 100644
--- a/plugins/PostProcessingPlugin/plugin.json
+++ b/plugins/PostProcessingPlugin/plugin.json
@@ -2,7 +2,7 @@
"name": "Post Processing",
"author": "Ultimaker",
"version": "2.2.1",
- "api": "6.0",
+ "api": "7.0",
"description": "Extension that allows for user created scripts for post processing",
"catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py
index be9f93c0f6..cdbb4a79ef 100644
--- a/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py
+++ b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py
@@ -100,8 +100,8 @@ class ChangeAtZ(Script):
},
"d_twLayers":
{
- "label": "No. Layers",
- "description": "No. of layers used to change",
+ "label": "Layer Spread",
+ "description": "The change will be gradual over this many layers. Enter 1 to make the change immediate.",
"unit": "",
"type": "int",
"default_value": 1,
@@ -330,7 +330,7 @@ class ChangeAtZ(Script):
"extruderOne": self.getSettingValueByKey("i2_extruderOne"),
"extruderTwo": self.getSettingValueByKey("i4_extruderTwo"),
"fanSpeed": self.getSettingValueByKey("j2_fanSpeed")}
- old = {"speed": -1, "flowrate": -1, "flowrateOne": -1, "flowrateTwo": -1, "platformTemp": -1, "extruderOne": -1,
+ old = {"speed": -1, "flowrate": 100, "flowrateOne": -1, "flowrateTwo": -1, "platformTemp": -1, "extruderOne": -1,
"extruderTwo": -1, "bedTemp": -1, "fanSpeed": -1, "state": -1}
twLayers = self.getSettingValueByKey("d_twLayers")
if self.getSettingValueByKey("c_behavior") == "single_layer":
@@ -367,6 +367,8 @@ class ChangeAtZ(Script):
modified_gcode = ""
lines = active_layer.split("\n")
for line in lines:
+ if line.strip() == "":
+ continue
if ";Generated with Cura_SteamEngine" in line:
TWinstances += 1
modified_gcode += ";ChangeAtZ instances: %d\n" % TWinstances
@@ -410,6 +412,8 @@ class ChangeAtZ(Script):
tmp_extruder = self.getValue(line, "T", None)
if tmp_extruder == None: #check if extruder is specified
old["flowrate"] = self.getValue(line, "S", old["flowrate"])
+ if old["flowrate"] == -1:
+ old["flowrate"] = 100.0
elif tmp_extruder == 0: #first extruder
old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"])
elif tmp_extruder == 1: #second extruder
@@ -481,9 +485,9 @@ class ChangeAtZ(Script):
state = 2
done_layers = 0
if targetL_i > -100000:
- modified_gcode += ";ChangeAtZ V%s: reset below Layer %d\n" % (self.version,targetL_i)
+ modified_gcode += ";ChangeAtZ V%s: reset below Layer %d\n" % (self.version, targetL_i)
else:
- modified_gcode += ";ChangeAtZ V%s: reset below %1.2f mm\n" % (self.version,targetZ)
+ modified_gcode += ";ChangeAtZ V%s: reset below %1.2f mm\n" % (self.version, targetZ)
if IsUM2 and oldValueUnknown: #executes on UM2 with Ultigcode and machine setting
modified_gcode += "M606 S%d;recalls saved settings\n" % (TWinstances-1)
else: #executes on RepRap, UM2 with Ultigcode and Cura setting
diff --git a/plugins/PostProcessingPlugin/scripts/DisplayFilenameAndLayerOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayFilenameAndLayerOnLCD.py
index 9fd9e08d7d..001beecd3b 100644
--- a/plugins/PostProcessingPlugin/scripts/DisplayFilenameAndLayerOnLCD.py
+++ b/plugins/PostProcessingPlugin/scripts/DisplayFilenameAndLayerOnLCD.py
@@ -1,10 +1,13 @@
# Cura PostProcessingPlugin
# Author: Amanda de Castilho
# Date: August 28, 2018
+# Modified: November 16, 2018 by Joshua Pope-Lewis
-# Description: This plugin inserts a line at the start of each layer,
-# M117 - displays the filename and layer height to the LCD
-# Alternatively, user can override the filename to display alt text + layer height
+# Description: This plugin shows custom messages about your print on the Status bar...
+# Please look at the 3 options
+# - Scolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you arent printing a small item select this option.
+# - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - Type a custom name in here
+# - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!)
from ..Script import Script
from UM.Application import Application
@@ -15,35 +18,72 @@ class DisplayFilenameAndLayerOnLCD(Script):
def getSettingDataString(self):
return """{
- "name": "Display filename and layer on LCD",
+ "name": "Display Filename And Layer On LCD",
"key": "DisplayFilenameAndLayerOnLCD",
"metadata": {},
"version": 2,
"settings":
{
+ "scroll":
+ {
+ "label": "Scroll enabled/Small layers?",
+ "description": "If SCROLL_LONG_FILENAMES is enabled select this setting however, if the model is small disable this setting!",
+ "type": "bool",
+ "default_value": false
+ },
"name":
{
- "label": "text to display:",
+ "label": "Text to display:",
"description": "By default the current filename will be displayed on the LCD. Enter text here to override the filename and display something else.",
"type": "str",
"default_value": ""
+ },
+ "startNum":
+ {
+ "label": "Initial layer number:",
+ "description": "Choose which number you prefer for the initial layer, 0 or 1",
+ "type": "int",
+ "default_value": 0,
+ "minimum_value": 0,
+ "maximum_value": 1
+ },
+ "maxlayer":
+ {
+ "label": "Display max layer?:",
+ "description": "Display how many layers are in the entire print on status bar?",
+ "type": "bool",
+ "default_value": true
}
}
}"""
def execute(self, data):
+ max_layer = 0
if self.getSettingValueByKey("name") != "":
name = self.getSettingValueByKey("name")
else:
- name = Application.getInstance().getPrintInformation().jobName
- lcd_text = "M117 " + name + " layer: "
- i = 0
+ name = Application.getInstance().getPrintInformation().jobName
+ if not self.getSettingValueByKey("scroll"):
+ if self.getSettingValueByKey("maxlayer"):
+ lcd_text = "M117 Layer "
+ else:
+ lcd_text = "M117 Printing Layer "
+ else:
+ lcd_text = "M117 Printing " + name + " - Layer "
+ i = self.getSettingValueByKey("startNum")
for layer in data:
- display_text = lcd_text + str(i)
+ display_text = lcd_text + str(i) + " " + name
layer_index = data.index(layer)
lines = layer.split("\n")
for line in lines:
+ if line.startswith(";LAYER_COUNT:"):
+ max_layer = line
+ max_layer = max_layer.split(":")[1]
if line.startswith(";LAYER:"):
+ if self.getSettingValueByKey("maxlayer"):
+ display_text = display_text + " of " + max_layer
+ else:
+ display_text = display_text + "!"
line_index = lines.index(line)
lines.insert(line_index + 1, display_text)
i += 1
diff --git a/plugins/PostProcessingPlugin/scripts/DisplayRemainingTimeOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayRemainingTimeOnLCD.py
new file mode 100644
index 0000000000..7d9af10925
--- /dev/null
+++ b/plugins/PostProcessingPlugin/scripts/DisplayRemainingTimeOnLCD.py
@@ -0,0 +1,94 @@
+# Cura PostProcessingPlugin
+# Author: Mathias Lyngklip Kjeldgaard
+# Date: July 31, 2019
+# Modified: November 26, 2019
+
+# Description: This plugin displayes the remaining time on the LCD of the printer
+# using the estimated print-time generated by Cura.
+
+
+
+
+from ..Script import Script
+
+import re
+import datetime
+
+
+class DisplayRemainingTimeOnLCD(Script):
+
+ def __init__(self):
+ super().__init__()
+
+
+ def getSettingDataString(self):
+ return """{
+ "name":"Display Remaining Time on LCD",
+ "key":"DisplayRemainingTimeOnLCD",
+ "metadata": {},
+ "version": 2,
+ "settings":
+ {
+ "TurnOn":
+ {
+ "label": "Enable",
+ "description": "When enabled, It will write Time Left: HHMMSS on the display. This is updated every layer.",
+ "type": "bool",
+ "default_value": false
+ }
+ }
+ }"""
+
+ def execute(self, data):
+ if self.getSettingValueByKey("TurnOn"):
+ total_time = 0
+ total_time_string = ""
+ for layer in data:
+ layer_index = data.index(layer)
+ lines = layer.split("\n")
+ for line in lines:
+ if line.startswith(";TIME:"):
+ # At this point, we have found a line in the GCODE with ";TIME:"
+ # which is the indication of total_time. Looks like: ";TIME:1337", where
+ # 1337 is the total print time in seconds.
+ line_index = lines.index(line) # We take a hold of that line
+ split_string = re.split(":", line) # Then we split it, so we can get the number
+
+ string_with_numbers = "{}".format(split_string[1]) # Here we insert that number from the
+ # list into a string.
+ total_time = int(string_with_numbers) # Only to contert it to a int.
+
+ m, s = divmod(total_time, 60) # Math to calculate
+ h, m = divmod(m, 60) # hours, minutes and seconds.
+ total_time_string = "{:d}h{:02d}m{:02d}s".format(h, m, s) # Now we put it into the string
+ lines[line_index] = "M117 Time Left {}".format(total_time_string) # And print that string instead of the original one
+
+
+
+
+ elif line.startswith(";TIME_ELAPSED:"):
+
+ # As we didnt find the total time (";TIME:"), we have found a elapsed time mark
+ # This time represents the time the printer have printed. So with some math;
+ # totalTime - printTime = RemainingTime.
+ line_index = lines.index(line) # We get a hold of the line
+ list_split = re.split(":", line) # Again, we split at ":" so we can get the number
+ string_with_numbers = "{}".format(list_split[1]) # Then we put that number from the list, into a string
+
+ current_time = float(string_with_numbers) # This time we convert to a float, as the line looks something like:
+ # ;TIME_ELAPSED:1234.6789
+ # which is total time in seconds
+
+ time_left = total_time - current_time # Here we calculate remaining time
+ m1, s1 = divmod(time_left, 60) # And some math to get the total time in seconds into
+ h1, m1 = divmod(m1, 60) # the right format. (HH,MM,SS)
+ current_time_string = "{:d}h{:2d}m{:2d}s".format(int(h1), int(m1), int(s1)) # Here we create the string holding our time
+ lines[line_index] = "M117 Time Left {}".format(current_time_string) # And now insert that into the GCODE
+
+
+ # Here we are OUT of the second for-loop
+ # Which means we have found and replaces all the occurences.
+ # Which also means we are ready to join the lines for that section of the GCODE file.
+ final_lines = "\n".join(lines)
+ data[layer_index] = final_lines
+ return data
diff --git a/plugins/PostProcessingPlugin/scripts/FilamentChange.py b/plugins/PostProcessingPlugin/scripts/FilamentChange.py
index febb93be4c..943ca30f2e 100644
--- a/plugins/PostProcessingPlugin/scripts/FilamentChange.py
+++ b/plugins/PostProcessingPlugin/scripts/FilamentChange.py
@@ -1,9 +1,7 @@
# Copyright (c) 2019 Ultimaker B.V.
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
-from typing import Optional, Tuple
-
-from UM.Logger import Logger
+from typing import List
from ..Script import Script
class FilamentChange(Script):
@@ -65,9 +63,10 @@ class FilamentChange(Script):
}
}"""
- def execute(self, data: list):
-
- """data is a list. Each index contains a layer"""
+ ## Inserts the filament change g-code at specific layer numbers.
+ # \param data A list of layers of g-code.
+ # \return A similar list, with filament change commands inserted.
+ def execute(self, data: List[str]):
layer_nums = self.getSettingValueByKey("layer_number")
initial_retract = self.getSettingValueByKey("initial_retract")
later_retract = self.getSettingValueByKey("later_retract")
@@ -88,32 +87,16 @@ class FilamentChange(Script):
if y_pos is not None:
color_change = color_change + (" Y%.2f" % y_pos)
- color_change = color_change + " ; Generated by FilamentChange plugin"
+ color_change = color_change + " ; Generated by FilamentChange plugin\n"
layer_targets = layer_nums.split(",")
if len(layer_targets) > 0:
for layer_num in layer_targets:
- layer_num = int(layer_num.strip())
- if layer_num <= len(data):
- index, layer_data = self._searchLayerData(data, layer_num - 1)
- if layer_data is None:
- Logger.log("e", "Could not found the layer")
- continue
- lines = layer_data.split("\n")
- lines.insert(2, color_change)
- final_line = "\n".join(lines)
- data[index] = final_line
+ try:
+ layer_num = int(layer_num.strip()) + 1 #Needs +1 because the 1st layer is reserved for start g-code.
+ except ValueError: #Layer number is not an integer.
+ continue
+ if 0 < layer_num < len(data):
+ data[layer_num] = color_change + data[layer_num]
- return data
-
- ## This method returns the data corresponding with the indicated layer number, looking in the gcode for
- # the occurrence of this layer number.
- def _searchLayerData(self, data: list, layer_num: int) -> Tuple[int, Optional[str]]:
- for index, layer_data in enumerate(data):
- first_line = layer_data.split("\n")[0]
- # The first line should contain the layer number at the beginning.
- if first_line[:len(self._layer_keyword)] == self._layer_keyword:
- # If found the layer that we are looking for, then return the data
- if first_line[len(self._layer_keyword):] == str(layer_num):
- return index, layer_data
- return 0, None
\ No newline at end of file
+ return data
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py
index 32fcc85fe1..c21993aad1 100644
--- a/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py
+++ b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py
@@ -37,13 +37,14 @@ class InsertAtLayerChange(Script):
for layer in data:
# Check that a layer is being printed
lines = layer.split("\n")
- if ";LAYER:" in lines[0]:
- index = data.index(layer)
- if self.getSettingValueByKey("insert_location") == "before":
- layer = gcode_to_add + layer
- else:
- layer = layer + gcode_to_add
-
- data[index] = layer
+ for line in lines:
+ if ";LAYER:" in line:
+ index = data.index(layer)
+ if self.getSettingValueByKey("insert_location") == "before":
+ layer = gcode_to_add + layer
+ else:
+ layer = layer + gcode_to_add
+ data[index] = layer
+ break
return data
diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
index 8b50a88b7f..17b4de88dd 100644
--- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
+++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
@@ -1,15 +1,18 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from ..Script import Script
from UM.Application import Application #To get the current printer's settings.
+from UM.Logger import Logger
+
+from typing import List, Tuple
class PauseAtHeight(Script):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
- def getSettingDataString(self):
+ def getSettingDataString(self) -> str:
return """{
"name": "Pause at height",
"key": "PauseAtHeight",
@@ -105,19 +108,24 @@ class PauseAtHeight(Script):
"standby_temperature":
{
"label": "Standby Temperature",
- "description": "Change the temperature during the pause",
+ "description": "Change the temperature during the pause.",
"unit": "°C",
"type": "int",
"default_value": 0
+ },
+ "display_text":
+ {
+ "label": "Display Text",
+ "description": "Text that should appear on the display while paused. If left empty, there will not be any message.",
+ "type": "str",
+ "default_value": ""
}
}
}"""
- def getNextXY(self, layer: str):
- """
- Get the X and Y values for a layer (will be used to get X and Y of
- the layer after the pause
- """
+ ## Get the X and Y values for a layer (will be used to get X and Y of the
+ # layer after the pause).
+ def getNextXY(self, layer: str) -> Tuple[float, float]:
lines = layer.split("\n")
for line in lines:
if self.getValue(line, "X") is not None and self.getValue(line, "Y") is not None:
@@ -126,8 +134,10 @@ class PauseAtHeight(Script):
return x, y
return 0, 0
- def execute(self, data: list):
- """data is a list. Each index contains a layer"""
+ ## Inserts the pause commands.
+ # \param data: List of layers.
+ # \return New list of layers.
+ def execute(self, data: List[str]) -> List[str]:
pause_at = self.getSettingValueByKey("pause_at")
pause_height = self.getSettingValueByKey("pause_height")
pause_layer = self.getSettingValueByKey("pause_layer")
@@ -143,6 +153,7 @@ class PauseAtHeight(Script):
firmware_retract = Application.getInstance().getGlobalContainerStack().getProperty("machine_firmware_retract", "value")
control_temperatures = Application.getInstance().getGlobalContainerStack().getProperty("machine_nozzle_temp_enabled", "value")
initial_layer_height = Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")
+ display_text = self.getSettingValueByKey("display_text")
is_griffin = False
@@ -151,6 +162,9 @@ class PauseAtHeight(Script):
# use offset to calculate the current height: = -
layer_0_z = 0
current_z = 0
+ current_height = 0
+ current_layer = 0
+ current_extrusion_f = 0
got_first_g_cmd_on_layer_0 = False
current_t = 0 #Tracks the current extruder for tracking the target temperature.
target_temperature = {} #Tracks the current target temperature for each extruder.
@@ -184,6 +198,10 @@ class PauseAtHeight(Script):
if not layers_started:
continue
+ # Look for the feed rate of an extrusion instruction
+ if self.getValue(line, "F") is not None and self.getValue(line, "E") is not None:
+ current_extrusion_f = self.getValue(line, "F")
+
# If a Z instruction is in the line, read the current Z
if self.getValue(line, "Z") is not None:
current_z = self.getValue(line, "Z")
@@ -201,7 +219,7 @@ class PauseAtHeight(Script):
current_height = current_z - layer_0_z
if current_height < pause_height:
- break # Try the next layer.
+ continue # Scan the enitre layer, z-changes are not always on the same/first line.
# Pause at layer
else:
@@ -247,8 +265,8 @@ class PauseAtHeight(Script):
# the nozzle)
x, y = self.getNextXY(layer)
prev_lines = prev_layer.split("\n")
- for line in prev_lines:
- new_e = self.getValue(line, 'E', current_e)
+ for lin in prev_lines:
+ new_e = self.getValue(lin, "E", current_e)
if new_e != current_e:
current_e = new_e
break
@@ -264,7 +282,7 @@ class PauseAtHeight(Script):
if not is_griffin:
# Retraction
- prepend_gcode += self.putValue(M = 83) + "\n"
+ prepend_gcode += self.putValue(M = 83) + " ; switch to relative E values for any needed retraction\n"
if retraction_amount != 0:
if firmware_retract: #Can't set the distance directly to what the user wants. We have to choose ourselves.
retraction_count = 1 if control_temperatures else 3 #Retract more if we don't control the temperature.
@@ -274,25 +292,28 @@ class PauseAtHeight(Script):
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
# Move the head away
- prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
+ prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + " ; move up a millimeter to get out of the way\n"
# This line should be ok
prepend_gcode += self.putValue(G = 1, X = park_x, Y = park_y, F = 9000) + "\n"
if current_z < 15:
- prepend_gcode += self.putValue(G = 1, Z = 15, F = 300) + "\n"
+ prepend_gcode += self.putValue(G = 1, Z = 15, F = 300) + " ; too close to bed--move to at least 15mm\n"
if control_temperatures:
# Set extruder standby temperature
- prepend_gcode += self.putValue(M = 104, S = standby_temperature) + "; standby temperature\n"
+ prepend_gcode += self.putValue(M = 104, S = standby_temperature) + " ; standby temperature\n"
+
+ if display_text:
+ prepend_gcode += "M117 " + display_text + "\n"
# Wait till the user continues printing
- prepend_gcode += self.putValue(M = 0) + ";Do the actual pause\n"
+ prepend_gcode += self.putValue(M = 0) + " ; Do the actual pause\n"
if not is_griffin:
if control_temperatures:
# Set extruder resume temperature
- prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, 0))) + "; resume temperature\n"
+ prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, 0))) + " ; resume temperature\n"
# Push the filament back,
if retraction_amount != 0:
@@ -308,8 +329,10 @@ class PauseAtHeight(Script):
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
# Move the head back
- prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
+ if current_z < 15:
+ prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
prepend_gcode += self.putValue(G = 1, X = x, Y = y, F = 9000) + "\n"
+ prepend_gcode += self.putValue(G = 1, Z = current_z, F = 300) + " ; move back down to resume height\n"
if retraction_amount != 0:
if firmware_retract: #Can't set the distance directly to what the user wants. We have to choose ourselves.
retraction_count = 1 if control_temperatures else 3 #Retract more if we don't control the temperature.
@@ -317,8 +340,13 @@ class PauseAtHeight(Script):
prepend_gcode += self.putValue(G = 11) + "\n"
else:
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
- prepend_gcode += self.putValue(G = 1, F = 9000) + "\n"
- prepend_gcode += self.putValue(M = 82) + "\n"
+
+ if current_extrusion_f != 0:
+ prepend_gcode += self.putValue(G = 1, F = current_extrusion_f) + " ; restore extrusion feedrate\n"
+ else:
+ Logger.log("w", "No previous feedrate found in gcode, feedrate for next layer(s) might be incorrect")
+
+ prepend_gcode += self.putValue(M = 82) + " ; switch back to absolute E values\n"
# reset extrude value to pre pause value
prepend_gcode += self.putValue(G = 92, E = current_e) + "\n"
diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py
index f6c93d9ae6..0353574289 100644
--- a/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py
+++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py
@@ -1,3 +1,4 @@
+from UM.Logger import Logger
from ..Script import Script
class PauseAtHeightforRepetier(Script):
def __init__(self):
@@ -73,6 +74,7 @@ class PauseAtHeightforRepetier(Script):
def execute(self, data):
x = 0.
y = 0.
+ current_extrusion_f = 0
current_z = 0.
pause_z = self.getSettingValueByKey("pause_height")
retraction_amount = self.getSettingValueByKey("retraction_amount")
@@ -94,9 +96,11 @@ class PauseAtHeightforRepetier(Script):
if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0:
current_z = self.getValue(line, 'Z')
+ if self.getValue(line, 'F') is not None and self.getValue(line, 'E') is not None:
+ current_extrusion_f = self.getValue(line, 'F', current_extrusion_f)
x = self.getValue(line, 'X', x)
y = self.getValue(line, 'Y', y)
- if current_z != None:
+ if current_z is not None:
if current_z >= pause_z:
index = data.index(layer)
@@ -150,7 +154,12 @@ class PauseAtHeightforRepetier(Script):
prepend_gcode +="G1 X%f Y%f F9000\n" % (x, y)
if retraction_amount != 0:
prepend_gcode +="G1 E%f F6000\n" % (retraction_amount)
- prepend_gcode +="G1 F9000\n"
+
+ if current_extrusion_f != 0:
+ prepend_gcode += self.putValue(G=1, F=current_extrusion_f) + " ; restore extrusion feedrate\n"
+ else:
+ Logger.log("w", "No previous feedrate found in gcode, feedrate for next layer(s) might be incorrect")
+
prepend_gcode +="M82\n"
# reset extrude value to pre pause value
diff --git a/plugins/PostProcessingPlugin/scripts/RetractContinue.py b/plugins/PostProcessingPlugin/scripts/RetractContinue.py
new file mode 100644
index 0000000000..b0af9cd95e
--- /dev/null
+++ b/plugins/PostProcessingPlugin/scripts/RetractContinue.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
+
+import math
+
+from ..Script import Script
+
+## Continues retracting during all travel moves.
+class RetractContinue(Script):
+ def getSettingDataString(self):
+ return """{
+ "name": "Retract Continue",
+ "key": "RetractContinue",
+ "metadata": {},
+ "version": 2,
+ "settings":
+ {
+ "extra_retraction_speed":
+ {
+ "label": "Extra Retraction Ratio",
+ "description": "How much does it retract during the travel move, by ratio of the travel length.",
+ "type": "float",
+ "default_value": 0.05
+ }
+ }
+ }"""
+
+ def execute(self, data):
+ current_e = 0
+ current_x = 0
+ current_y = 0
+ extra_retraction_speed = self.getSettingValueByKey("extra_retraction_speed")
+
+ for layer_number, layer in enumerate(data):
+ lines = layer.split("\n")
+ for line_number, line in enumerate(lines):
+ if self.getValue(line, "G") in {0, 1}: # Track X,Y location.
+ current_x = self.getValue(line, "X", current_x)
+ current_y = self.getValue(line, "Y", current_y)
+ if self.getValue(line, "G") == 1:
+ if self.getValue(line, "E"):
+ new_e = self.getValue(line, "E")
+ if new_e >= current_e: # Not a retraction.
+ continue
+ # A retracted travel move may consist of multiple commands, due to combing.
+ # This continues retracting over all of these moves and only unretracts at the end.
+ delta_line = 1
+ dx = current_x # Track the difference in X for this move only to compute the length of the travel.
+ dy = current_y
+ while line_number + delta_line < len(lines) and self.getValue(lines[line_number + delta_line], "G") != 1:
+ travel_move = lines[line_number + delta_line]
+ if self.getValue(travel_move, "G") != 0:
+ delta_line += 1
+ continue
+ travel_x = self.getValue(travel_move, "X", dx)
+ travel_y = self.getValue(travel_move, "Y", dy)
+ f = self.getValue(travel_move, "F", "no f")
+ length = math.sqrt((travel_x - dx) * (travel_x - dx) + (travel_y - dy) * (travel_y - dy)) # Length of the travel move.
+ new_e -= length * extra_retraction_speed # New retraction is by ratio of this travel move.
+ if f == "no f":
+ new_travel_move = "G1 X{travel_x} Y{travel_y} E{new_e}".format(travel_x = travel_x, travel_y = travel_y, new_e = new_e)
+ else:
+ new_travel_move = "G1 F{f} X{travel_x} Y{travel_y} E{new_e}".format(f = f, travel_x = travel_x, travel_y = travel_y, new_e = new_e)
+ lines[line_number + delta_line] = new_travel_move
+
+ delta_line += 1
+ dx = travel_x
+ dy = travel_y
+
+ current_e = new_e
+
+ new_layer = "\n".join(lines)
+ data[layer_number] = new_layer
+
+ return data
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/scripts/Stretch.py b/plugins/PostProcessingPlugin/scripts/Stretch.py
index 9757296041..20eef60ef2 100644
--- a/plugins/PostProcessingPlugin/scripts/Stretch.py
+++ b/plugins/PostProcessingPlugin/scripts/Stretch.py
@@ -128,9 +128,26 @@ class Stretcher():
onestep = GCodeStep(0, in_relative_movement)
onestep.copyPosFrom(current)
elif _getValue(line, "G") == 1:
+ last_x = current.step_x
+ last_y = current.step_y
+ last_z = current.step_z
+ last_e = current.step_e
current.readStep(line)
- onestep = GCodeStep(1, in_relative_movement)
- onestep.copyPosFrom(current)
+ if (current.step_x == last_x and current.step_y == last_y and
+ current.step_z == last_z and current.step_e != last_e
+ ):
+ # It's an extruder only move. Preserve it rather than process it as an
+ # extruded move. Otherwise, the stretched output might contain slight
+ # motion in X and Y in addition to E. This can cause problems with
+ # firmwares that implement pressure advance.
+ onestep = GCodeStep(-1, in_relative_movement)
+ onestep.copyPosFrom(current)
+ # Rather than copy the original line, write a new one with consistent
+ # extruder coordinates
+ onestep.comment = "G1 F{} E{}".format(onestep.step_f, onestep.step_e)
+ else:
+ onestep = GCodeStep(1, in_relative_movement)
+ onestep.copyPosFrom(current)
# end of relative movement
elif _getValue(line, "G") == 90:
@@ -145,6 +162,7 @@ class Stretcher():
current.readStep(line)
onestep = GCodeStep(-1, in_relative_movement)
onestep.copyPosFrom(current)
+ onestep.comment = line
else:
onestep = GCodeStep(-1, in_relative_movement)
onestep.copyPosFrom(current)
diff --git a/plugins/PostProcessingPlugin/scripts/TimeLapse.py b/plugins/PostProcessingPlugin/scripts/TimeLapse.py
index 76d9143459..53e55a9454 100644
--- a/plugins/PostProcessingPlugin/scripts/TimeLapse.py
+++ b/plugins/PostProcessingPlugin/scripts/TimeLapse.py
@@ -77,18 +77,19 @@ class TimeLapse(Script):
gcode_to_append = ";TimeLapse Begin\n"
if park_print_head:
- gcode_to_append += self.putValue(G = 1, F = feed_rate, X = x_park, Y = y_park) + ";Park print head\n"
- gcode_to_append += self.putValue(M = 400) + ";Wait for moves to finish\n"
- gcode_to_append += trigger_command + ";Snap Photo\n"
- gcode_to_append += self.putValue(G = 4, P = pause_length) + ";Wait for camera\n"
+ gcode_to_append += self.putValue(G = 1, F = feed_rate, X = x_park, Y = y_park) + " ;Park print head\n"
+ gcode_to_append += self.putValue(M = 400) + " ;Wait for moves to finish\n"
+ gcode_to_append += trigger_command + " ;Snap Photo\n"
+ gcode_to_append += self.putValue(G = 4, P = pause_length) + " ;Wait for camera\n"
gcode_to_append += ";TimeLapse End\n"
for layer in data:
# Check that a layer is being printed
lines = layer.split("\n")
- if ";LAYER:" in lines[0]:
- index = data.index(layer)
- layer += gcode_to_append
-
- data[index] = layer
+ for line in lines:
+ if ";LAYER:" in line:
+ index = data.index(layer)
+ layer += gcode_to_append
+ data[index] = layer
+ break
return data
diff --git a/plugins/PostProcessingPlugin/scripts/UsePreviousProbeMeasurements.py b/plugins/PostProcessingPlugin/scripts/UsePreviousProbeMeasurements.py
new file mode 100644
index 0000000000..271cb57100
--- /dev/null
+++ b/plugins/PostProcessingPlugin/scripts/UsePreviousProbeMeasurements.py
@@ -0,0 +1,46 @@
+# Cura PostProcessingPlugin
+# Author: Amanda de Castilho
+# Date: January 5,2019
+
+# Description: This plugin overrides probing command and inserts code to ensure
+# previous probe measurements are loaded and bed leveling enabled
+# (searches for G29 and replaces it with M501 & M420 S1)
+# *** Assumes G29 is in the start code, will do nothing if it isn't ***
+
+from ..Script import Script
+
+class UsePreviousProbeMeasurements(Script):
+ def __init__(self):
+ super().__init__()
+
+ def getSettingDataString(self):
+ return """{
+ "name": "Use Previous Probe Measurements",
+ "key": "UsePreviousProbeMeasurements",
+ "metadata": {},
+ "version": 2,
+ "settings":
+ {
+ "use_previous_measurements":
+ {
+ "label": "Use last measurement?",
+ "description": "Selecting this will remove the G29 probing command and instead ensure previous measurements are loaded and enabled",
+ "type": "bool",
+ "default_value": false
+ }
+ }
+ }"""
+
+ def execute(self, data):
+ text = "M501 ;load bed level data\nM420 S1 ;enable bed leveling"
+ if self.getSettingValueByKey("use_previous_measurements"):
+ for layer in data:
+ layer_index = data.index(layer)
+ lines = layer.split("\n")
+ for line in lines:
+ if line.startswith("G29"):
+ line_index = lines.index(line)
+ lines[line_index] = text
+ final_lines = "\n".join(lines)
+ data[layer_index] = final_lines
+ return data
diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml
index d8953d7661..87d7c5f35c 100644
--- a/plugins/PrepareStage/PrepareMenu.qml
+++ b/plugins/PrepareStage/PrepareMenu.qml
@@ -20,11 +20,19 @@ Item
name: "cura"
}
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ leftMargin: UM.Theme.getSize("wide_margin").width
+ rightMargin: UM.Theme.getSize("wide_margin").width
+ }
+
// Item to ensure that all of the buttons are nicely centered.
Item
{
anchors.horizontalCenter: parent.horizontalCenter
- width: openFileButton.width + itemRow.width + UM.Theme.getSize("default_margin").width
+ width: parent.width - 2 * UM.Theme.getSize("wide_margin").width
height: parent.height
RowLayout
@@ -32,9 +40,9 @@ Item
id: itemRow
anchors.left: openFileButton.right
+ anchors.right: parent.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width
- width: Math.round(0.9 * prepareMenu.width)
height: parent.height
spacing: 0
diff --git a/plugins/PrepareStage/__init__.py b/plugins/PrepareStage/__init__.py
index f085d788f9..8e86ff303d 100644
--- a/plugins/PrepareStage/__init__.py
+++ b/plugins/PrepareStage/__init__.py
@@ -10,7 +10,7 @@ def getMetaData():
return {
"stage": {
"name": i18n_catalog.i18nc("@item:inmenu", "Prepare"),
- "weight": 0
+ "weight": 10
}
}
diff --git a/plugins/PrepareStage/plugin.json b/plugins/PrepareStage/plugin.json
index dc5c68ce16..e65c62ef49 100644
--- a/plugins/PrepareStage/plugin.json
+++ b/plugins/PrepareStage/plugin.json
@@ -1,8 +1,8 @@
-{
- "name": "Prepare Stage",
- "author": "Ultimaker B.V.",
- "version": "1.0.1",
- "description": "Provides a prepare stage in Cura.",
- "api": "6.0",
- "i18n-catalog": "cura"
+{
+ "name": "Prepare Stage",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.1",
+ "description": "Provides a prepare stage in Cura.",
+ "api": "7.0",
+ "i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/PreviewStage/PreviewMain.qml b/plugins/PreviewStage/PreviewMain.qml
index 6b5ce2436b..2926f0d012 100644
--- a/plugins/PreviewStage/PreviewMain.qml
+++ b/plugins/PreviewStage/PreviewMain.qml
@@ -11,12 +11,34 @@ import Cura 1.0 as Cura
Item
{
+
+ // An Item whose bounds are guaranteed to be safe for overlays to be placed.
+ // Defaults to parent, ie. the entire available area
+ property var safeArea: parent
+
+ // Subtract the actionPanel from the safe area. This way the view won't draw interface elements under/over it
+ Item
+ {
+ id: childSafeArea
+ x: safeArea.x - parent.x
+ y: safeArea.y - parent.y
+ width: actionPanelWidget.x - x
+ height: actionPanelWidget.y - y
+ }
+
Loader
{
id: previewMain
anchors.fill: parent
source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : ""
+
+ onLoaded:
+ {
+ if (previewMain.item.safeArea !== undefined){
+ previewMain.item.safeArea = Qt.binding(function() { return childSafeArea });
+ }
+ }
}
Cura.ActionPanelWidget
diff --git a/plugins/PreviewStage/PreviewMenu.qml b/plugins/PreviewStage/PreviewMenu.qml
index 62f814aac9..ff1ccff75f 100644
--- a/plugins/PreviewStage/PreviewMenu.qml
+++ b/plugins/PreviewStage/PreviewMenu.qml
@@ -20,15 +20,21 @@ Item
name: "cura"
}
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ leftMargin: UM.Theme.getSize("wide_margin").width
+ rightMargin: UM.Theme.getSize("wide_margin").width
+ }
+
Row
{
id: stageMenuRow
- anchors.centerIn: parent
- height: parent.height
- width: childrenRect.width
- // We want this row to have a preferred with equals to the 85% of the parent
- property int preferredWidth: Math.round(0.85 * previewMenu.width)
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width - 2 * UM.Theme.getSize("wide_margin").width
+ height: parent.height
Cura.ViewsSelector
{
@@ -49,12 +55,12 @@ Item
color: UM.Theme.getColor("lining")
}
- // This component will grow freely up to complete the preferredWidth of the row.
+ // This component will grow freely up to complete the width of the row.
Loader
{
id: viewPanel
height: parent.height
- width: source != "" ? (stageMenuRow.preferredWidth - viewsSelector.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width) : 0
+ width: source != "" ? (previewMenu.width - viewsSelector.width - printSetupSelectorItem.width - 2 * (UM.Theme.getSize("wide_margin").width + UM.Theme.getSize("default_lining").width)) : 0
source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : ""
}
diff --git a/plugins/PreviewStage/__init__.py b/plugins/PreviewStage/__init__.py
index 424f573e4a..cb32f583ee 100644
--- a/plugins/PreviewStage/__init__.py
+++ b/plugins/PreviewStage/__init__.py
@@ -11,7 +11,7 @@ def getMetaData():
return {
"stage": {
"name": i18n_catalog.i18nc("@item:inmenu", "Preview"),
- "weight": 1
+ "weight": 20
}
}
diff --git a/plugins/PreviewStage/plugin.json b/plugins/PreviewStage/plugin.json
index e1e4288bae..1c21e682ee 100644
--- a/plugins/PreviewStage/plugin.json
+++ b/plugins/PreviewStage/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides a preview stage in Cura.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py b/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py
index 51b6a70b7a..c89bd31e21 100644
--- a/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py
+++ b/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py
@@ -48,9 +48,13 @@ class WindowsRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
drives = {}
bitmask = ctypes.windll.kernel32.GetLogicalDrives()
- # Check possible drive letters, from A to Z
+ # Check possible drive letters, from C to Z
# Note: using ascii_uppercase because we do not want this to change with locale!
- for letter in string.ascii_uppercase:
+ # Skip A and B, since those drives are typically reserved for floppy disks.
+ # Those drives can theoretically be reassigned but it's safer to not check them for removable drives.
+ # Windows will also behave weirdly even with some of its internal functions if you do this (e.g. search indexing doesn't search it).
+ # Users that have removable drives in A or B will just have to save to file and select the drive there.
+ for letter in string.ascii_uppercase[2:]:
drive = "{0}:/".format(letter)
# Do we really want to skip A and B?
diff --git a/plugins/RemovableDriveOutputDevice/plugin.json b/plugins/RemovableDriveOutputDevice/plugin.json
index 5523d6b1c1..c794257e3a 100644
--- a/plugins/RemovableDriveOutputDevice/plugin.json
+++ b/plugins/RemovableDriveOutputDevice/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"description": "Provides removable drive hotplugging and writing support.",
"version": "1.0.1",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml
index 88f298d1f5..d6de45df9b 100644
--- a/plugins/SimulationView/LayerSlider.qml
+++ b/plugins/SimulationView/LayerSlider.qml
@@ -155,25 +155,19 @@ Item
}
onPositionChanged: parent.onHandleDragged()
- onPressed: sliderRoot.setActiveHandle(rangeHandle)
+ onPressed:
+ {
+ sliderRoot.setActiveHandle(rangeHandle)
+ sliderRoot.forceActiveFocus()
+ }
}
- SimulationSliderLabel
- {
- id: rangleHandleLabel
+ }
- height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
- x: parent.x - width - UM.Theme.getSize("default_margin").width
- anchors.verticalCenter: parent.verticalCenter
- target: Qt.point(sliderRoot.width, y + height / 2)
- visible: sliderRoot.activeHandle == parent
-
- // custom properties
- maximumValue: sliderRoot.maximumValue
- value: sliderRoot.upperValue
- busy: UM.SimulationView.busy
- setValue: rangeHandle.setValueManually // connect callback functions
- }
+ onHeightChanged : {
+ // After a height change, the pixel-position of the handles is out of sync with the property value
+ setLowerValue(lowerValue)
+ setUpperValue(upperValue)
}
// Upper handle
@@ -270,11 +264,12 @@ Item
{
id: upperHandleLabel
- height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
- x: parent.x - parent.width - width
- anchors.verticalCenter: parent.verticalCenter
- target: Qt.point(sliderRoot.width, y + height / 2)
- visible: sliderRoot.activeHandle == parent
+ height: sliderRoot.handleSize
+ anchors.bottom: parent.top
+ anchors.bottomMargin: UM.Theme.getSize("narrow_margin").height
+ anchors.horizontalCenter: parent.horizontalCenter
+ target: Qt.point(parent.width / 2, parent.top)
+ visible: sliderRoot.activeHandle == parent || sliderRoot.activeHandle == rangeHandle
// custom properties
maximumValue: sliderRoot.maximumValue
@@ -333,7 +328,6 @@ Item
// set the slider position based on the lower value
function setValue(value)
{
-
// Normalize values between range, since using arrow keys will create out-of-the-range values
value = sliderRoot.normalizeValue(value)
@@ -380,11 +374,12 @@ Item
{
id: lowerHandleLabel
- height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
- x: parent.x - parent.width - width
- anchors.verticalCenter: parent.verticalCenter
- target: Qt.point(sliderRoot.width + width, y + height / 2)
- visible: sliderRoot.activeHandle == parent
+ height: sliderRoot.handleSize
+ anchors.top: parent.bottom
+ anchors.topMargin: UM.Theme.getSize("narrow_margin").height
+ anchors.horizontalCenter: parent.horizontalCenter
+ target: Qt.point(parent.width / 2, parent.bottom)
+ visible: sliderRoot.activeHandle == parent || sliderRoot.activeHandle == rangeHandle
// custom properties
maximumValue: sliderRoot.maximumValue
@@ -393,4 +388,4 @@ Item
setValue: lowerHandle.setValueManually // connect callback functions
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/SimulationView/NozzleNode.py b/plugins/SimulationView/NozzleNode.py
index 8a29871775..11b788c128 100644
--- a/plugins/SimulationView/NozzleNode.py
+++ b/plugins/SimulationView/NozzleNode.py
@@ -3,7 +3,6 @@
from UM.Application import Application
from UM.Math.Color import Color
-from UM.Math.Vector import Vector
from UM.PluginRegistry import PluginRegistry
from UM.Scene.SceneNode import SceneNode
from UM.View.GL.OpenGL import OpenGL
diff --git a/plugins/SimulationView/PathSlider.qml b/plugins/SimulationView/PathSlider.qml
index c7a43c6407..facdbb6a53 100644
--- a/plugins/SimulationView/PathSlider.qml
+++ b/plugins/SimulationView/PathSlider.qml
@@ -56,6 +56,11 @@ Item
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
}
+ onWidthChanged : {
+ // After a width change, the pixel-position of the handle is out of sync with the property value
+ setHandleValue(handleValue)
+ }
+
// slider track
Rectangle
{
diff --git a/plugins/SimulationView/SimulationSliderLabel.qml b/plugins/SimulationView/SimulationSliderLabel.qml
index 06c6a51b44..c1fb0f4de9 100644
--- a/plugins/SimulationView/SimulationSliderLabel.qml
+++ b/plugins/SimulationView/SimulationSliderLabel.qml
@@ -1,7 +1,6 @@
// Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.2
+import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
@@ -20,9 +19,9 @@ UM.PointingRectangle {
property int startFrom: 1
target: Qt.point(parent.width, y + height / 2)
- arrowSize: UM.Theme.getSize("default_arrow").width
+ arrowSize: UM.Theme.getSize("button_tooltip_arrow").height
height: parent.height
- width: valueLabel.width + UM.Theme.getSize("default_margin").width
+ width: valueLabel.width
visible: false
color: UM.Theme.getColor("tool_panel_background")
@@ -40,26 +39,35 @@ UM.PointingRectangle {
anchors.fill: parent
}
+ TextMetrics {
+ id: maxValueMetrics
+ font: valueLabel.font
+ text: maximumValue + 1 // layers are 0 based, add 1 for display value
+
+ }
+
TextField {
id: valueLabel
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
+ alignWhenCentered: false
}
- width: ((maximumValue + 1).toString().length + 1) * 10 * screenScaleFactor
+ width: maxValueMetrics.width + UM.Theme.getSize("default_margin").width
text: sliderLabelRoot.value + startFrom // the current handle value, add 1 because layers is an array
- horizontalAlignment: TextInput.AlignRight
+ horizontalAlignment: TextInput.AlignHCenter
// key bindings, work when label is currenctly focused (active handle in LayerSlider)
Keys.onUpPressed: sliderLabelRoot.setValue(sliderLabelRoot.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
Keys.onDownPressed: sliderLabelRoot.setValue(sliderLabelRoot.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
style: TextFieldStyle {
- textColor: UM.Theme.getColor("setting_control_text")
+ textColor: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
- background: Item { }
+ renderType: Text.NativeRendering
+ background: Item { }
}
onEditingFinished: {
diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py
index 3b2db2efac..6d6f19c57c 100644
--- a/plugins/SimulationView/SimulationView.py
+++ b/plugins/SimulationView/SimulationView.py
@@ -48,7 +48,7 @@ if TYPE_CHECKING:
catalog = i18nCatalog("cura")
-## View used to display g-code paths.
+## The preview layer view. It is used to display g-code paths.
class SimulationView(CuraView):
# Must match SimulationViewMenuComponent.qml
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
@@ -83,9 +83,13 @@ class SimulationView(CuraView):
self._simulationview_composite_shader = None # type: Optional["ShaderProgram"]
self._old_composite_shader = None # type: Optional["ShaderProgram"]
+ self._max_feedrate = sys.float_info.min
+ self._min_feedrate = sys.float_info.max
+ self._max_thickness = sys.float_info.min
+ self._min_thickness = sys.float_info.max
+
self._global_container_stack = None # type: Optional[ContainerStack]
- self._proxy = SimulationViewProxy()
- self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged)
+ self._proxy = None
self._resetSettings()
self._legend_items = None
@@ -104,7 +108,6 @@ class SimulationView(CuraView):
Application.getInstance().getPreferences().addPreference("layerview/show_skin", True)
Application.getInstance().getPreferences().addPreference("layerview/show_infill", True)
- Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
self._updateWithPreferences()
self._solid_layers = int(Application.getInstance().getPreferences().getValue("view/top_layer_count"))
@@ -180,8 +183,7 @@ class SimulationView(CuraView):
def _onSceneChanged(self, node: "SceneNode") -> None:
if node.getMeshData() is None:
- self.resetLayerData()
-
+ return
self.setActivity(False)
self.calculateMaxLayers()
self.calculateMaxPathsOnLayer(self._current_layer_num)
@@ -211,6 +213,8 @@ class SimulationView(CuraView):
def beginRendering(self) -> None:
scene = self.getController().getScene()
renderer = self.getRenderer()
+ if renderer is None:
+ return
if not self._ghost_shader:
self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader"))
@@ -218,10 +222,10 @@ class SimulationView(CuraView):
if theme is not None:
self._ghost_shader.setUniformValue("u_color", Color(*theme.getColor("layerview_ghost").getRgb()))
- for node in DepthFirstIterator(scene.getRoot()): # type: ignore
+ for node in DepthFirstIterator(scene.getRoot()):
# We do not want to render ConvexHullNode as it conflicts with the bottom layers.
# However, it is somewhat relevant when the node is selected, so do render it then.
- if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()):
+ if type(node) is ConvexHullNode and not Selection.isSelected(cast(ConvexHullNode, node).getWatchedNode()):
continue
if not node.render(renderer):
@@ -384,7 +388,7 @@ class SimulationView(CuraView):
self._max_thickness = max(float(p.lineThicknesses.max()), self._max_thickness)
try:
self._min_thickness = min(float(p.lineThicknesses[numpy.nonzero(p.lineThicknesses)].min()), self._min_thickness)
- except:
+ except ValueError:
# Sometimes, when importing a GCode the line thicknesses are zero and so the minimum (avoiding
# the zero) can't be calculated
Logger.log("i", "Min thickness can't be calculated because all the values are zero")
@@ -441,6 +445,8 @@ class SimulationView(CuraView):
## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created
# as this caused some issues.
def getProxy(self, engine, script_engine):
+ if self._proxy is None:
+ self._proxy = SimulationViewProxy(self)
return self._proxy
def endRendering(self) -> None:
@@ -460,6 +466,13 @@ class SimulationView(CuraView):
return True
if event.type == Event.ViewActivateEvent:
+ # Start listening to changes.
+ Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
+ self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged)
+
+ self.calculateMaxLayers()
+ self.calculateMaxPathsOnLayer(self._current_layer_num)
+
# FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching.
# This can happen when you do the following steps:
# 1. Start Cura
@@ -479,7 +492,11 @@ class SimulationView(CuraView):
# Make sure the SimulationPass is created
layer_pass = self.getSimulationPass()
- self.getRenderer().addRenderPass(layer_pass)
+ renderer = self.getRenderer()
+ if renderer is None:
+ return False
+
+ renderer.addRenderPass(layer_pass)
# Make sure the NozzleNode is add to the root
nozzle = self.getNozzleNode()
@@ -498,7 +515,7 @@ class SimulationView(CuraView):
self._simulationview_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb()))
if not self._composite_pass:
- self._composite_pass = cast(CompositePass, self.getRenderer().getRenderPass("composite"))
+ self._composite_pass = cast(CompositePass, renderer.getRenderPass("composite"))
self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later
self._composite_pass.getLayerBindings().append("simulationview")
@@ -506,13 +523,21 @@ class SimulationView(CuraView):
self._composite_pass.setCompositeShader(self._simulationview_composite_shader)
elif event.type == Event.ViewDeactivateEvent:
+ self._controller.getScene().getRoot().childrenChanged.disconnect(self._onSceneChanged)
+ Application.getInstance().getPreferences().preferenceChanged.disconnect(self._onPreferencesChanged)
self._wireprint_warning_message.hide()
Application.getInstance().globalContainerStackChanged.disconnect(self._onGlobalStackChanged)
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged)
if self._nozzle_node:
self._nozzle_node.setParent(None)
- self.getRenderer().removeRenderPass(self._layer_pass)
+
+ renderer = self.getRenderer()
+ if renderer is None:
+ return False
+
+ if self._layer_pass is not None:
+ renderer.removeRenderPass(self._layer_pass)
if self._composite_pass:
self._composite_pass.setLayerBindings(cast(List[str], self._old_layer_bindings))
self._composite_pass.setCompositeShader(cast(ShaderProgram, self._old_composite_shader))
@@ -572,14 +597,14 @@ class SimulationView(CuraView):
self._current_layer_jumps = job.getResult().get("jumps")
self._controller.getScene().sceneChanged.emit(self._controller.getScene().getRoot())
- self._top_layers_job = None # type: Optional["_CreateTopLayersJob"]
+ self._top_layers_job = None
def _updateWithPreferences(self) -> None:
self._solid_layers = int(Application.getInstance().getPreferences().getValue("view/top_layer_count"))
self._only_show_top_layers = bool(Application.getInstance().getPreferences().getValue("view/only_show_top_layers"))
self._compatibility_mode = self._evaluateCompatibilityMode()
- self.setSimulationViewType(int(float(Application.getInstance().getPreferences().getValue("layerview/layer_view_type"))));
+ self.setSimulationViewType(int(float(Application.getInstance().getPreferences().getValue("layerview/layer_view_type"))))
for extruder_nr, extruder_opacity in enumerate(Application.getInstance().getPreferences().getValue("layerview/extruder_opacities").split("|")):
try:
diff --git a/plugins/SimulationView/SimulationViewMainComponent.qml b/plugins/SimulationView/SimulationViewMainComponent.qml
index 58901652d3..bfd8799673 100644
--- a/plugins/SimulationView/SimulationViewMainComponent.qml
+++ b/plugins/SimulationView/SimulationViewMainComponent.qml
@@ -11,19 +11,39 @@ import Cura 1.0 as Cura
Item
{
- property bool is_simulation_playing: false
+ // An Item whose bounds are guaranteed to be safe for overlays to be placed.
+ // Defaults to parent, ie. the entire available area
+ // eg. the layer slider will not be placed in this area.
+ property var safeArea: parent
+
+
+ property bool isSimulationPlaying: false
+ readonly property real layerSliderSafeYMin: safeArea.y
+ readonly property real layerSliderSafeYMax: safeArea.y + safeArea.height
+ readonly property real pathSliderSafeXMin: safeArea.x + playButton.width
+ readonly property real pathSliderSafeXMax: safeArea.x + safeArea.width
+
visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
+ // A slider which lets users trace a single layer (XY movements)
PathSlider
{
id: pathSlider
+
+ readonly property real preferredWidth: UM.Theme.getSize("slider_layerview_size").height // not a typo, should be as long as layerview slider
+ readonly property real margin: UM.Theme.getSize("default_margin").width
+ readonly property real pathSliderSafeWidth: pathSliderSafeXMax - pathSliderSafeXMin
+
height: UM.Theme.getSize("slider_handle").width
- width: UM.Theme.getSize("slider_layerview_size").height
+ width: preferredWidth + margin * 2 < pathSliderSafeWidth ? preferredWidth : pathSliderSafeWidth - margin * 2
+
anchors.bottom: parent.bottom
- anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+ anchors.bottomMargin: margin
anchors.horizontalCenter: parent.horizontalCenter
+ anchors.horizontalCenterOffset: -(parent.width - pathSliderSafeXMax - pathSliderSafeXMin) / 2 // center between parent top and layerSliderSafeYMax
+
visible: !UM.SimulationView.compatibilityMode
@@ -58,7 +78,7 @@ Item
UM.SimpleButton
{
id: playButton
- iconSource: !is_simulation_playing ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
+ iconSource: !isSimulationPlaying ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg"
width: UM.Theme.getSize("small_button").width
height: UM.Theme.getSize("small_button").height
hoverColor: UM.Theme.getColor("slider_handle_active")
@@ -88,7 +108,7 @@ Item
onClicked:
{
- if(is_simulation_playing)
+ if(isSimulationPlaying)
{
pauseSimulation()
}
@@ -102,7 +122,7 @@ Item
{
UM.SimulationView.setSimulationRunning(false)
simulationTimer.stop()
- is_simulation_playing = false
+ isSimulationPlaying = false
layerSlider.manuallyChanged = true
pathSlider.manuallyChanged = true
}
@@ -131,7 +151,7 @@ Item
// When the user plays the simulation, if the path slider is at the end of this layer, we start
// the simulation at the beginning of the current layer.
- if (!is_simulation_playing)
+ if (!isSimulationPlaying)
{
if (currentPath >= numPaths)
{
@@ -166,22 +186,30 @@ Item
}
// The status must be set here instead of in the resumeSimulation function otherwise it won't work
// correctly, because part of the logic is in this trigger function.
- is_simulation_playing = true
+ isSimulationPlaying = true
}
}
+ // Scrolls trough Z layers
LayerSlider
{
+ property var preferredHeight: UM.Theme.getSize("slider_layerview_size").height
+ property double heightMargin: UM.Theme.getSize("default_margin").height * 3 // extra margin to accomodate layer number tooltips
+ property double layerSliderSafeHeight: layerSliderSafeYMax - layerSliderSafeYMin
+
id: layerSlider
width: UM.Theme.getSize("slider_handle").width
- height: UM.Theme.getSize("slider_layerview_size").height
+ height: preferredHeight + heightMargin * 2 < layerSliderSafeHeight ? preferredHeight : layerSliderSafeHeight - heightMargin * 2
anchors
{
right: parent.right
verticalCenter: parent.verticalCenter
+ verticalCenterOffset: -(parent.height - layerSliderSafeYMax - layerSliderSafeYMin) / 2 // center between parent top and layerSliderSafeYMax
rightMargin: UM.Theme.getSize("default_margin").width
+ bottomMargin: heightMargin
+ topMargin: heightMargin
}
// Custom properties
diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml
index 957d8170cf..b94cf029f0 100644
--- a/plugins/SimulationView/SimulationViewMenuComponent.qml
+++ b/plugins/SimulationView/SimulationViewMenuComponent.qml
@@ -15,6 +15,8 @@ Cura.ExpandableComponent
{
id: base
+ dragPreferencesNamePrefix: "view/colorscheme"
+
contentHeaderTitle: catalog.i18nc("@label", "Color scheme")
Connections
@@ -177,7 +179,6 @@ Cura.ExpandableComponent
height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
width: parent.width
visible: !UM.SimulationView.compatibilityMode
- enabled: index < 4
onClicked:
{
diff --git a/plugins/SimulationView/SimulationViewProxy.py b/plugins/SimulationView/SimulationViewProxy.py
index a84b151983..58a004cc31 100644
--- a/plugins/SimulationView/SimulationViewProxy.py
+++ b/plugins/SimulationView/SimulationViewProxy.py
@@ -1,21 +1,24 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
from UM.FlameProfiler import pyqtSlot
from UM.Application import Application
-import SimulationView
+if TYPE_CHECKING:
+ from .SimulationView import SimulationView
class SimulationViewProxy(QObject):
- def __init__(self, parent=None):
+ def __init__(self, simulation_view: "SimulationView", parent=None):
super().__init__(parent)
+ self._simulation_view = simulation_view
self._current_layer = 0
self._controller = Application.getInstance().getController()
self._controller.activeViewChanged.connect(self._onActiveViewChanged)
- self._onActiveViewChanged()
self.is_simulationView_selected = False
+ self._onActiveViewChanged()
currentLayerChanged = pyqtSignal()
currentPathChanged = pyqtSignal()
@@ -28,182 +31,112 @@ class SimulationViewProxy(QObject):
@pyqtProperty(bool, notify=activityChanged)
def layerActivity(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getActivity()
- return False
+ return self._simulation_view.getActivity()
@pyqtProperty(int, notify=maxLayersChanged)
def numLayers(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMaxLayers()
- return 0
+ return self._simulation_view.getMaxLayers()
@pyqtProperty(int, notify=currentLayerChanged)
def currentLayer(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getCurrentLayer()
- return 0
+ return self._simulation_view.getCurrentLayer()
@pyqtProperty(int, notify=currentLayerChanged)
def minimumLayer(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMinimumLayer()
- return 0
+ return self._simulation_view.getMinimumLayer()
@pyqtProperty(int, notify=maxPathsChanged)
def numPaths(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMaxPaths()
- return 0
+ return self._simulation_view.getMaxPaths()
@pyqtProperty(int, notify=currentPathChanged)
def currentPath(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getCurrentPath()
- return 0
+ return self._simulation_view.getCurrentPath()
@pyqtProperty(int, notify=currentPathChanged)
def minimumPath(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMinimumPath()
- return 0
+ return self._simulation_view.getMinimumPath()
@pyqtProperty(bool, notify=busyChanged)
def busy(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.isBusy()
- return False
+ return self._simulation_view.isBusy()
@pyqtProperty(bool, notify=preferencesChanged)
def compatibilityMode(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getCompatibilityMode()
- return False
+ return self._simulation_view.getCompatibilityMode()
+
+ @pyqtProperty(int, notify=globalStackChanged)
+ def extruderCount(self):
+ return self._simulation_view.getExtruderCount()
@pyqtSlot(int)
def setCurrentLayer(self, layer_num):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setLayer(layer_num)
+ self._simulation_view.setLayer(layer_num)
@pyqtSlot(int)
def setMinimumLayer(self, layer_num):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setMinimumLayer(layer_num)
+ self._simulation_view.setMinimumLayer(layer_num)
@pyqtSlot(int)
def setCurrentPath(self, path_num):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setPath(path_num)
+ self._simulation_view.setPath(path_num)
@pyqtSlot(int)
def setMinimumPath(self, path_num):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setMinimumPath(path_num)
+ self._simulation_view.setMinimumPath(path_num)
@pyqtSlot(int)
def setSimulationViewType(self, layer_view_type):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setSimulationViewType(layer_view_type)
+ self._simulation_view.setSimulationViewType(layer_view_type)
@pyqtSlot(result=int)
def getSimulationViewType(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getSimulationViewType()
- return 0
+ return self._simulation_view.getSimulationViewType()
@pyqtSlot(bool)
def setSimulationRunning(self, running):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setSimulationRunning(running)
+ self._simulation_view.setSimulationRunning(running)
@pyqtSlot(result=bool)
def getSimulationRunning(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.isSimulationRunning()
- return False
+ return self._simulation_view.isSimulationRunning()
@pyqtSlot(result=float)
def getMinFeedrate(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMinFeedrate()
- return 0
+ return self._simulation_view.getMinFeedrate()
@pyqtSlot(result=float)
def getMaxFeedrate(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMaxFeedrate()
- return 0
+ return self._simulation_view.getMaxFeedrate()
@pyqtSlot(result=float)
def getMinThickness(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMinThickness()
- return 0
+ return self._simulation_view.getMinThickness()
@pyqtSlot(result=float)
def getMaxThickness(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getMaxThickness()
- return 0
+ return self._simulation_view.getMaxThickness()
# Opacity 0..1
@pyqtSlot(int, float)
def setExtruderOpacity(self, extruder_nr, opacity):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setExtruderOpacity(extruder_nr, opacity)
+ self._simulation_view.setExtruderOpacity(extruder_nr, opacity)
@pyqtSlot(int)
def setShowTravelMoves(self, show):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setShowTravelMoves(show)
+ self._simulation_view.setShowTravelMoves(show)
@pyqtSlot(int)
def setShowHelpers(self, show):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setShowHelpers(show)
+ self._simulation_view.setShowHelpers(show)
@pyqtSlot(int)
def setShowSkin(self, show):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setShowSkin(show)
+ self._simulation_view.setShowSkin(show)
@pyqtSlot(int)
def setShowInfill(self, show):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- active_view.setShowInfill(show)
-
- @pyqtProperty(int, notify=globalStackChanged)
- def extruderCount(self):
- active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- return active_view.getExtruderCount()
- return 0
+ self._simulation_view.setShowInfill(show)
def _layerActivityChanged(self):
self.activityChanged.emit()
@@ -236,24 +169,25 @@ class SimulationViewProxy(QObject):
def _onActiveViewChanged(self):
active_view = self._controller.getActiveView()
- if isinstance(active_view, SimulationView.SimulationView.SimulationView):
- # remove other connection if once the SimulationView was created.
- if self.is_simulationView_selected:
- active_view.currentLayerNumChanged.disconnect(self._onLayerChanged)
- active_view.currentPathNumChanged.disconnect(self._onPathChanged)
- active_view.maxLayersChanged.disconnect(self._onMaxLayersChanged)
- active_view.maxPathsChanged.disconnect(self._onMaxPathsChanged)
- active_view.busyChanged.disconnect(self._onBusyChanged)
- active_view.activityChanged.disconnect(self._onActivityChanged)
- active_view.globalStackChanged.disconnect(self._onGlobalStackChanged)
- active_view.preferencesChanged.disconnect(self._onPreferencesChanged)
-
+ if active_view == self._simulation_view:
+ self._simulation_view.currentLayerNumChanged.connect(self._onLayerChanged)
+ self._simulation_view.currentPathNumChanged.connect(self._onPathChanged)
+ self._simulation_view.maxLayersChanged.connect(self._onMaxLayersChanged)
+ self._simulation_view.maxPathsChanged.connect(self._onMaxPathsChanged)
+ self._simulation_view.busyChanged.connect(self._onBusyChanged)
+ self._simulation_view.activityChanged.connect(self._onActivityChanged)
+ self._simulation_view.globalStackChanged.connect(self._onGlobalStackChanged)
+ self._simulation_view.preferencesChanged.connect(self._onPreferencesChanged)
self.is_simulationView_selected = True
- active_view.currentLayerNumChanged.connect(self._onLayerChanged)
- active_view.currentPathNumChanged.connect(self._onPathChanged)
- active_view.maxLayersChanged.connect(self._onMaxLayersChanged)
- active_view.maxPathsChanged.connect(self._onMaxPathsChanged)
- active_view.busyChanged.connect(self._onBusyChanged)
- active_view.activityChanged.connect(self._onActivityChanged)
- active_view.globalStackChanged.connect(self._onGlobalStackChanged)
- active_view.preferencesChanged.connect(self._onPreferencesChanged)
+ elif self.is_simulationView_selected:
+ # Disconnect all of em again.
+ self.is_simulationView_selected = False
+ self._simulation_view.currentLayerNumChanged.disconnect(self._onLayerChanged)
+ self._simulation_view.currentPathNumChanged.disconnect(self._onPathChanged)
+ self._simulation_view.maxLayersChanged.disconnect(self._onMaxLayersChanged)
+ self._simulation_view.maxPathsChanged.disconnect(self._onMaxPathsChanged)
+ self._simulation_view.busyChanged.disconnect(self._onBusyChanged)
+ self._simulation_view.activityChanged.disconnect(self._onActivityChanged)
+ self._simulation_view.globalStackChanged.disconnect(self._onGlobalStackChanged)
+ self._simulation_view.preferencesChanged.disconnect(self._onPreferencesChanged)
+
diff --git a/plugins/SimulationView/layers.shader b/plugins/SimulationView/layers.shader
index 69c7c61ee5..11b049c9fe 100644
--- a/plugins/SimulationView/layers.shader
+++ b/plugins/SimulationView/layers.shader
@@ -1,6 +1,9 @@
[shaders]
vertex =
- uniform highp mat4 u_modelViewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform lowp float u_active_extruder;
uniform lowp float u_shade_factor;
uniform highp int u_layer_view_type;
@@ -16,7 +19,7 @@ vertex =
void main()
{
- gl_Position = u_modelViewProjectionMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
// shade the color depending on the extruder index
v_color = a_color;
// 8 and 9 are travel moves
@@ -76,7 +79,10 @@ fragment =
vertex41core =
#version 410
- uniform highp mat4 u_modelViewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform lowp float u_active_extruder;
uniform lowp float u_shade_factor;
uniform highp int u_layer_view_type;
@@ -92,7 +98,7 @@ vertex41core =
void main()
{
- gl_Position = u_modelViewProjectionMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
v_color = a_color;
if ((a_line_type != 8) && (a_line_type != 9)) {
v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a);
@@ -154,7 +160,9 @@ u_show_skin = 1
u_show_infill = 1
[bindings]
-u_modelViewProjectionMatrix = model_view_projection_matrix
+u_modelMatrix = model_matrix
+u_viewMatrix = view_matrix
+u_projectionMatrix = projection_matrix
[attributes]
a_vertex = vertex
diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader
index a277606509..ecd96c3f68 100644
--- a/plugins/SimulationView/layers3d.shader
+++ b/plugins/SimulationView/layers3d.shader
@@ -1,10 +1,10 @@
[shaders]
vertex41core =
#version 410
- uniform highp mat4 u_modelViewProjectionMatrix;
-
uniform highp mat4 u_modelMatrix;
- uniform highp mat4 u_viewProjectionMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform lowp float u_active_extruder;
uniform lowp float u_max_feedrate;
uniform lowp float u_min_feedrate;
@@ -104,7 +104,10 @@ vertex41core =
geometry41core =
#version 410
- uniform highp mat4 u_viewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform int u_show_travel_moves;
uniform int u_show_helpers;
uniform int u_show_skin;
@@ -136,6 +139,8 @@ geometry41core =
void main()
{
+ highp mat4 viewProjectionMatrix = u_projectionMatrix * u_viewMatrix;
+
vec4 g_vertex_delta;
vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers
vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position
@@ -183,65 +188,83 @@ geometry41core =
g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0);
if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) {
+ vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert);
+ vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert);
+ vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert);
+ vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert);
+ vec4 vb_down = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert);
+ vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert);
+
// Travels: flat plane with pointy ends
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert));
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_head);
//And reverse so that the line is also visible from the back side.
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
EndPrimitive();
} else {
+ vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz);
+ vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz);
+ vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert);
+ vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert);
+ vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz);
+ vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz);
+ vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert);
+ vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert);
+ vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head);
+ vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head);
+
// All normal lines are rendered as 3d tubes.
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
EndPrimitive();
// left side
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
EndPrimitive();
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
EndPrimitive();
// right side
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
EndPrimitive();
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz));
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
EndPrimitive();
}
@@ -301,9 +324,9 @@ u_min_thickness = 0
u_max_thickness = 1
[bindings]
-u_modelViewProjectionMatrix = model_view_projection_matrix
u_modelMatrix = model_matrix
-u_viewProjectionMatrix = view_projection_matrix
+u_viewMatrix = view_matrix
+u_projectionMatrix = projection_matrix
u_normalMatrix = normal_matrix
u_lightPosition = light_0_position
diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader
index 15136fcf3f..b2ed7f8c12 100644
--- a/plugins/SimulationView/layers3d_shadow.shader
+++ b/plugins/SimulationView/layers3d_shadow.shader
@@ -1,10 +1,10 @@
[shaders]
vertex41core =
#version 410
- uniform highp mat4 u_modelViewProjectionMatrix;
-
uniform highp mat4 u_modelMatrix;
- uniform highp mat4 u_viewProjectionMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform lowp float u_active_extruder;
uniform lowp vec4 u_extruder_opacity; // currently only for max 4 extruders, others always visible
@@ -58,7 +58,10 @@ vertex41core =
geometry41core =
#version 410
- uniform highp mat4 u_viewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform int u_show_travel_moves;
uniform int u_show_helpers;
uniform int u_show_skin;
@@ -90,6 +93,8 @@ geometry41core =
void main()
{
+ highp mat4 viewProjectionMatrix = u_projectionMatrix * u_viewMatrix;
+
vec4 g_vertex_delta;
vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers
vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position
@@ -137,65 +142,83 @@ geometry41core =
g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0);
if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) {
+ vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert);
+ vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert);
+ vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert);
+ vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert);
+ vec4 vb_down = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert);
+ vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert);
+
// Travels: flat plane with pointy ends
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert));
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_head);
//And reverse so that the line is also visible from the back side.
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert));
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up);
EndPrimitive();
} else {
+ vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz);
+ vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz);
+ vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert);
+ vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert);
+ vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz);
+ vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz);
+ vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert);
+ vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert);
+ vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head);
+ vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head);
+
// All normal lines are rendered as 3d tubes.
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
EndPrimitive();
// left side
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
EndPrimitive();
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz));
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert);
+ myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head);
+ myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz);
EndPrimitive();
// right side
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
EndPrimitive();
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert));
- myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head));
- myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz));
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert);
+ myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head);
+ myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz);
EndPrimitive();
}
@@ -246,9 +269,9 @@ u_show_skin = 1
u_show_infill = 1
[bindings]
-u_modelViewProjectionMatrix = model_view_projection_matrix
u_modelMatrix = model_matrix
-u_viewProjectionMatrix = view_projection_matrix
+u_viewMatrix = view_matrix
+u_projectionMatrix = projection_matrix
u_normalMatrix = normal_matrix
u_lightPosition = light_0_position
diff --git a/plugins/SimulationView/layers_shadow.shader b/plugins/SimulationView/layers_shadow.shader
index 6149cc1703..8f500536a5 100644
--- a/plugins/SimulationView/layers_shadow.shader
+++ b/plugins/SimulationView/layers_shadow.shader
@@ -1,6 +1,9 @@
[shaders]
vertex =
- uniform highp mat4 u_modelViewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform lowp float u_active_extruder;
uniform lowp float u_shade_factor;
uniform highp int u_layer_view_type;
@@ -16,7 +19,7 @@ vertex =
void main()
{
- gl_Position = u_modelViewProjectionMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
// shade the color depending on the extruder index
v_color = vec4(0.4, 0.4, 0.4, 0.9); // default color for not current layer;
// 8 and 9 are travel moves
@@ -80,7 +83,10 @@ fragment =
vertex41core =
#version 410
- uniform highp mat4 u_modelViewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
+
uniform lowp float u_active_extruder;
uniform lowp float u_shade_factor;
uniform highp int u_layer_view_type;
@@ -96,7 +102,7 @@ vertex41core =
void main()
{
- gl_Position = u_modelViewProjectionMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
v_color = vec4(0.4, 0.4, 0.4, 0.9); // default color for not current layer
// if ((a_line_type != 8) && (a_line_type != 9)) {
// v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a);
@@ -159,7 +165,9 @@ u_show_skin = 1
u_show_infill = 1
[bindings]
-u_modelViewProjectionMatrix = model_view_projection_matrix
+u_modelMatrix = model_matrix
+u_viewMatrix = view_matrix
+u_projectionMatrix = projection_matrix
[attributes]
a_vertex = vertex
diff --git a/plugins/SimulationView/plugin.json b/plugins/SimulationView/plugin.json
index 3ccf91b9e6..e444f1fa2e 100644
--- a/plugins/SimulationView/plugin.json
+++ b/plugins/SimulationView/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides the Simulation view.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml
index e00ad6730d..50276ec25c 100644
--- a/plugins/SliceInfoPlugin/MoreInfoWindow.qml
+++ b/plugins/SliceInfoPlugin/MoreInfoWindow.qml
@@ -1,150 +1,156 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
+import QtQuick.Controls 2.3
import QtQuick.Window 2.2
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
import UM 1.3 as UM
-import Cura 1.0 as Cura
+import Cura 1.1 as Cura
-UM.Dialog
+Window
{
+ UM.I18nCatalog { id: catalog; name: "cura" }
+
id: baseDialog
title: catalog.i18nc("@title:window", "More information on anonymous data collection")
visible: false
+ modality: Qt.ApplicationModal
+
minimumWidth: 500 * screenScaleFactor
minimumHeight: 400 * screenScaleFactor
width: minimumWidth
height: minimumHeight
- property bool allowSendData: true // for saving the user's choice
+ color: UM.Theme.getColor("main_background")
- onAccepted: manager.setSendSliceInfo(allowSendData)
+ property bool allowSendData: true // for saving the user's choice
onVisibilityChanged:
{
if (visible)
{
- baseDialog.allowSendData = UM.Preferences.getValue("info/send_slice_info");
+ baseDialog.allowSendData = UM.Preferences.getValue("info/send_slice_info")
if (baseDialog.allowSendData)
{
- allowSendButton.checked = true;
+ allowSendButton.checked = true
}
else
{
- dontSendButton.checked = true;
+ dontSendButton.checked = true
}
}
}
+ // Main content area
Item
{
- id: textRow
- anchors
- {
- top: parent.top
- bottom: radioButtonsRow.top
- bottomMargin: UM.Theme.getSize("default_margin").height
- left: parent.left
- right: parent.right
- }
+ anchors.fill: parent
+ anchors.margins: UM.Theme.getSize("default_margin").width
- Label
+ Item // Text part
{
- id: headerText
+ id: textRow
anchors
{
top: parent.top
- left: parent.left
- right: parent.right
- }
-
- text: catalog.i18nc("@text:window", "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent.")
- wrapMode: Text.WordWrap
- }
-
- TextArea
- {
- id: exampleData
- anchors
- {
- top: headerText.bottom
- topMargin: UM.Theme.getSize("default_margin").height
- bottom: parent.bottom
+ bottom: radioButtonsRow.top
bottomMargin: UM.Theme.getSize("default_margin").height
left: parent.left
right: parent.right
}
- text: manager.getExampleData()
- readOnly: true
- textFormat: TextEdit.PlainText
- }
- }
-
- Column
- {
- id: radioButtonsRow
- width: parent.width
- anchors.bottom: buttonRow.top
- anchors.bottomMargin: UM.Theme.getSize("default_margin").height
-
- ExclusiveGroup { id: group }
-
- RadioButton
- {
- id: dontSendButton
- text: catalog.i18nc("@text:window", "I don't want to send this data")
- exclusiveGroup: group
- onClicked:
+ Label
{
- baseDialog.allowSendData = !checked;
+ id: headerText
+ anchors
+ {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ text: catalog.i18nc("@text:window", "Ultimaker Cura collects anonymous data in order to improve the print quality and user experience. Below is an example of all the data that is shared:")
+ wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
}
- }
- RadioButton
- {
- id: allowSendButton
- text: catalog.i18nc("@text:window", "Allow sending this data to Ultimaker and help us improve Cura")
- exclusiveGroup: group
- onClicked:
+
+ Cura.ScrollableTextArea
{
- baseDialog.allowSendData = checked;
- }
- }
- }
+ anchors
+ {
+ top: headerText.bottom
+ topMargin: UM.Theme.getSize("default_margin").height
+ bottom: parent.bottom
+ bottomMargin: UM.Theme.getSize("default_margin").height
+ left: parent.left
+ right: parent.right
+ }
- Item
- {
- id: buttonRow
- anchors.bottom: parent.bottom
- width: parent.width
- anchors.bottomMargin: UM.Theme.getSize("default_margin").height
-
- UM.I18nCatalog { id: catalog; name: "cura" }
-
- Button
- {
- anchors.right: parent.right
- text: catalog.i18nc("@action:button", "OK")
- onClicked:
- {
- baseDialog.accepted()
- baseDialog.hide()
+ textArea.text: manager.getExampleData()
+ textArea.textFormat: Text.RichText
+ textArea.wrapMode: Text.Wrap
+ textArea.readOnly: true
}
}
- Button
+ Column // Radio buttons for agree and disagree
{
+ id: radioButtonsRow
anchors.left: parent.left
- text: catalog.i18nc("@action:button", "Cancel")
- onClicked:
+ anchors.right: parent.right
+ anchors.bottom: buttonRow.top
+ anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+
+ Cura.RadioButton
{
- baseDialog.rejected()
- baseDialog.hide()
+ id: dontSendButton
+ text: catalog.i18nc("@text:window", "I don't want to send anonymous data")
+ onClicked:
+ {
+ baseDialog.allowSendData = !checked
+ }
+ }
+ Cura.RadioButton
+ {
+ id: allowSendButton
+ text: catalog.i18nc("@text:window", "Allow sending anonymous data")
+ onClicked:
+ {
+ baseDialog.allowSendData = checked
+ }
+ }
+ }
+
+ Item // Bottom buttons
+ {
+ id: buttonRow
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ height: childrenRect.height
+
+ Cura.PrimaryButton
+ {
+ anchors.right: parent.right
+ text: catalog.i18nc("@action:button", "OK")
+ onClicked:
+ {
+ manager.setSendSliceInfo(allowSendData)
+ baseDialog.hide()
+ }
+ }
+
+ Cura.SecondaryButton
+ {
+ anchors.left: parent.left
+ text: catalog.i18nc("@action:button", "Cancel")
+ onClicked:
+ {
+ baseDialog.hide()
+ }
}
}
}
diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py
index 5149b6a6a6..af8a8b9853 100755
--- a/plugins/SliceInfoPlugin/SliceInfo.py
+++ b/plugins/SliceInfoPlugin/SliceInfo.py
@@ -18,6 +18,8 @@ from UM.Logger import Logger
from UM.PluginRegistry import PluginRegistry
from UM.Qt.Duration import DurationFormat
+from cura import ApplicationMetadata
+
from .SliceInfoJob import SliceInfoJob
@@ -48,20 +50,6 @@ class SliceInfo(QObject, Extension):
def _onAppInitialized(self):
# DO NOT read any preferences values in the constructor because at the time plugins are created, no version
# upgrade has been performed yet because version upgrades are plugins too!
- if not self._application.getPreferences().getValue("info/asked_send_slice_info"):
- self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymized usage statistics."),
- lifetime = 0,
- dismissable = False,
- title = catalog.i18nc("@info:title", "Collecting Data"))
-
- self.send_slice_info_message.addAction("MoreInfo", name = catalog.i18nc("@action:button", "More info"), icon = None,
- description = catalog.i18nc("@action:tooltip", "See more information on what data Cura sends."), button_style = Message.ActionButtonStyle.LINK)
-
- self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None,
- description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."))
- self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
- self.send_slice_info_message.show()
-
if self._more_info_dialog is None:
self._more_info_dialog = self._createDialog("MoreInfoWindow.qml")
@@ -76,7 +64,7 @@ class SliceInfo(QObject, Extension):
def showMoreInfoDialog(self):
if self._more_info_dialog is None:
self._more_info_dialog = self._createDialog("MoreInfoWindow.qml")
- self._more_info_dialog.open()
+ self._more_info_dialog.show()
def _createDialog(self, qml_name):
Logger.log("d", "Creating dialog [%s]", qml_name)
@@ -91,7 +79,7 @@ class SliceInfo(QObject, Extension):
if not plugin_path:
Logger.log("e", "Could not get plugin path!", self.getPluginId())
return None
- file_path = os.path.join(plugin_path, "example_data.json")
+ file_path = os.path.join(plugin_path, "example_data.html")
if file_path:
with open(file_path, "r", encoding = "utf-8") as f:
self._example_data_content = f.read()
@@ -133,6 +121,7 @@ class SliceInfo(QObject, Extension):
data["time_stamp"] = time.time()
data["schema_version"] = 0
data["cura_version"] = application.getVersion()
+ data["cura_build_type"] = ApplicationMetadata.CuraBuildType
active_mode = Application.getInstance().getPreferences().getValue("cura/active_mode")
if active_mode == 0:
@@ -140,6 +129,10 @@ class SliceInfo(QObject, Extension):
else:
data["active_mode"] = "custom"
+ data["camera_view"] = application.getPreferences().getValue("general/camera_perspective_mode")
+ if data["camera_view"] == "orthographic":
+ data["camera_view"] = "orthogonal" #The database still only recognises the old name "orthogonal".
+
definition_changes = global_stack.definitionChanges
machine_settings_changed_by_user = False
if definition_changes.getId() != "empty":
@@ -184,6 +177,7 @@ class SliceInfo(QObject, Extension):
extruder_dict["extruder_settings"] = extruder_settings
data["extruders"].append(extruder_dict)
+ data["intent_category"] = global_stack.getIntentCategory()
data["quality_profile"] = global_stack.quality.getMetaData().get("quality_type")
data["user_modified_setting_keys"] = self._getUserModifiedSettingKeys()
@@ -195,6 +189,8 @@ class SliceInfo(QObject, Extension):
model = dict()
model["hash"] = node.getMeshData().getHash()
bounding_box = node.getBoundingBox()
+ if not bounding_box:
+ continue
model["bounding_box"] = {"minimum": {"x": bounding_box.minimum.x,
"y": bounding_box.minimum.y,
"z": bounding_box.minimum.z},
diff --git a/plugins/SliceInfoPlugin/SliceInfoJob.py b/plugins/SliceInfoPlugin/SliceInfoJob.py
index a5667c1c13..50d6b560f1 100644
--- a/plugins/SliceInfoPlugin/SliceInfoJob.py
+++ b/plugins/SliceInfoPlugin/SliceInfoJob.py
@@ -8,6 +8,8 @@ import ssl
import urllib.request
import urllib.error
+import certifi
+
class SliceInfoJob(Job):
def __init__(self, url, data):
@@ -20,11 +22,14 @@ class SliceInfoJob(Job):
Logger.log("e", "URL or DATA for sending slice info was not set!")
return
- # Submit data
- kwoptions = {"data" : self._data, "timeout" : 5}
+ # CURA-6698 Create an SSL context and use certifi CA certificates for verification.
+ context = ssl.SSLContext(protocol = ssl.PROTOCOL_TLSv1_2)
+ context.load_verify_locations(cafile = certifi.where())
- if Platform.isOSX():
- kwoptions["context"] = ssl._create_unverified_context()
+ # Submit data
+ kwoptions = {"data": self._data,
+ "timeout": 5,
+ "context": context}
Logger.log("i", "Sending anonymous slice info to [%s]...", self._url)
@@ -35,4 +40,4 @@ class SliceInfoJob(Job):
except urllib.error.HTTPError:
Logger.logException("e", "An HTTP error occurred while trying to send slice information")
except Exception: # We don't want any exception to cause problems
- Logger.logException("e", "An exception occurred while trying to send slice information")
\ No newline at end of file
+ Logger.logException("e", "An exception occurred while trying to send slice information")
diff --git a/plugins/SliceInfoPlugin/example_data.html b/plugins/SliceInfoPlugin/example_data.html
new file mode 100644
index 0000000000..103eb55a6a
--- /dev/null
+++ b/plugins/SliceInfoPlugin/example_data.html
@@ -0,0 +1,65 @@
+
+
+ Cura Version: 4.0
+ Operating System: Windows 10
+ Language: en_US
+ Machine Type: Ultimaker S5
+ Intent Profile: Default
+ Quality Profile: Fast
+ Using Custom Settings: No
+
+
Extruder 1:
+
+
Material Type: PLA
+
Print Core: AA 0.4
+
Material Used: 1240 mm
+
+
+
Extruder 2:
+
+
Material Type: PVA
+
Print Core: BB 0.4
+
Material Used: 432 mm
+
+
+
Print Settings:
+
+
Layer Height: 0.15
+
Wall Line Count: 3
+
Enable Retraction: no
+
Infill Density: 20%
+
Infill Pattern: triangles
+
Gradual Infill Steps: 0
+
Printing Temperature: 220 °C
+
Generate Support: yes
+
Support Extruder: 1
+
Build Plate Adhesion Type: brim
+
Enable Prime Tower: yes
+
Print Sequence: All at once
+
...
+
+
+
Model Information:
+
+
+ Model 1
+
+
Hash: b72789b9b...
+
Transformation: [transformation matrix]
+
Bounding Box: [minimum x, y, z; maximum x, y, z]
+
Is Helper Mesh: no
+
Helper Mesh Type: support mesh
+
+
+
+
+
Print Times:
+
+
Infill: 61200 sec.
+
Support: 25480 sec.
+
Travel: 6224 sec.
+
Walls: 10225 sec.
+
Total: 103129 sec.
+
+
+
diff --git a/plugins/SliceInfoPlugin/example_data.json b/plugins/SliceInfoPlugin/example_data.json
deleted file mode 100644
index 5fc4175e60..0000000000
--- a/plugins/SliceInfoPlugin/example_data.json
+++ /dev/null
@@ -1,114 +0,0 @@
-{
- "time_stamp": 1523973715.486928,
- "schema_version": 0,
- "cura_version": "3.3",
- "active_mode": "custom",
- "machine_settings_changed_by_user": true,
- "language": "en_US",
- "os": {
- "type": "Linux",
- "version": "#43~16.04.1-Ubuntu SMP Wed Mar 14 17:48:43 UTC 2018"
- },
- "active_machine": {
- "definition_id": "ultimaker3",
- "manufacturer": "Ultimaker B.V."
- },
- "extruders": [
- {
- "active": true,
- "material": {
- "GUID": "506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9",
- "type": "PLA",
- "brand": "Generic"
- },
- "material_used": 0.84,
- "variant": "AA 0.4",
- "nozzle_size": 0.4,
- "extruder_settings": {
- "wall_line_count": 3,
- "retraction_enable": true,
- "infill_sparse_density": 30,
- "infill_pattern": "triangles",
- "gradual_infill_steps": 0,
- "default_material_print_temperature": 200,
- "material_print_temperature": 200
- }
- },
- {
- "active": false,
- "material": {
- "GUID": "86a89ceb-4159-47f6-ab97-e9953803d70f",
- "type": "PVA",
- "brand": "Generic"
- },
- "material_used": 0.5,
- "variant": "BB 0.4",
- "nozzle_size": 0.4,
- "extruder_settings": {
- "wall_line_count": 3,
- "retraction_enable": true,
- "infill_sparse_density": 20,
- "infill_pattern": "triangles",
- "gradual_infill_steps": 0,
- "default_material_print_temperature": 215,
- "material_print_temperature": 220
- }
- }
- ],
- "quality_profile": "fast",
- "user_modified_setting_keys": ["layer_height", "wall_line_width", "infill_sparse_density"],
- "models": [
- {
- "hash": "b72789b9beb5366dff20b1cf501020c3d4d4df7dc2295ecd0fddd0a6436df070",
- "bounding_box": {
- "minimum": {
- "x": -10.0,
- "y": 0.0,
- "z": -5.0
- },
- "maximum": {
- "x": 9.999999046325684,
- "y": 40.0,
- "z": 5.0
- }
- },
- "transformation": {
- "data": "[[ 1. 0. 0. 0.] [ 0. 1. 0. 20.] [ 0. 0. 1. 0.] [ 0. 0. 0. 1.]]"
- },
- "extruder": 0,
- "model_settings": {
- "support_enabled": true,
- "support_extruder_nr": 1,
- "infill_mesh": false,
- "cutting_mesh": false,
- "support_mesh": false,
- "anti_overhang_mesh": false,
- "wall_line_count": 3,
- "retraction_enable": true,
- "infill_sparse_density": 30,
- "infill_pattern": "triangles",
- "gradual_infill_steps": 0
- }
- }
- ],
- "print_times": {
- "travel": 187,
- "support": 825,
- "infill": 351,
- "total": 7234
- },
- "print_settings": {
- "layer_height": 0.15,
- "support_enabled": true,
- "support_extruder_nr": 1,
- "adhesion_type": "brim",
- "wall_line_count": 3,
- "retraction_enable": true,
- "prime_tower_enable": true,
- "infill_sparse_density": 20,
- "infill_pattern": "triangles",
- "gradual_infill_steps": 0,
- "print_sequence": "all_at_once"
- },
- "output_to": "LocalFileOutputDevice"
-}
diff --git a/plugins/SliceInfoPlugin/plugin.json b/plugins/SliceInfoPlugin/plugin.json
index 8ff0e194fb..8975f52591 100644
--- a/plugins/SliceInfoPlugin/plugin.json
+++ b/plugins/SliceInfoPlugin/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Submits anonymous slice info. Can be disabled through preferences.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py
index ec00329f86..61954f5bca 100644
--- a/plugins/SolidView/SolidView.py
+++ b/plugins/SolidView/SolidView.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.View.View import View
@@ -7,7 +7,6 @@ from UM.Scene.Selection import Selection
from UM.Resources import Resources
from UM.Application import Application
from UM.View.RenderBatch import RenderBatch
-from UM.Settings.Validator import ValidatorState
from UM.Math.Color import Color
from UM.View.GL.OpenGL import OpenGL
@@ -20,9 +19,9 @@ import math
class SolidView(View):
def __init__(self):
super().__init__()
-
- Application.getInstance().getPreferences().addPreference("view/show_overhang", True)
-
+ application = Application.getInstance()
+ application.getPreferences().addPreference("view/show_overhang", True)
+ application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
self._enabled_shader = None
self._disabled_shader = None
self._non_printing_shader = None
@@ -30,6 +29,41 @@ class SolidView(View):
self._extruders_model = None
self._theme = None
+ self._support_angle = 90
+
+ self._global_stack = None
+
+ Application.getInstance().engineCreatedSignal.connect(self._onGlobalContainerChanged)
+
+ def _onGlobalContainerChanged(self) -> None:
+ if self._global_stack:
+ try:
+ self._global_stack.propertyChanged.disconnect(self._onPropertyChanged)
+ except TypeError:
+ pass
+ for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
+ extruder_stack.propertyChanged.disconnect(self._onPropertyChanged)
+
+ self._global_stack = Application.getInstance().getGlobalContainerStack()
+ if self._global_stack:
+ self._global_stack.propertyChanged.connect(self._onPropertyChanged)
+ for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
+ extruder_stack.propertyChanged.connect(self._onPropertyChanged)
+ self._onPropertyChanged("support_angle", "value") # Force an re-evaluation
+
+ def _onPropertyChanged(self, key: str, property_name: str) -> None:
+ if key != "support_angle" or property_name != "value":
+ return
+ # As the rendering is called a *lot* we really, dont want to re-evaluate the property every time. So we store em!
+ global_container_stack = Application.getInstance().getGlobalContainerStack()
+ if global_container_stack:
+ support_extruder_nr = int(global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr"))
+ try:
+ support_angle_stack = global_container_stack.extruderList[support_extruder_nr]
+ except IndexError:
+ pass
+ else:
+ self._support_angle = support_angle_stack.getProperty("support_angle", "value")
def beginRendering(self):
scene = self.getController().getScene()
@@ -63,14 +97,10 @@ class SolidView(View):
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
- support_extruder_nr = global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr")
- support_angle_stack = Application.getInstance().getExtruderManager().getExtruderStack(support_extruder_nr)
-
- if support_angle_stack is not None and Application.getInstance().getPreferences().getValue("view/show_overhang"):
- angle = support_angle_stack.getProperty("support_angle", "value")
+ if Application.getInstance().getPreferences().getValue("view/show_overhang"):
# Make sure the overhang angle is valid before passing it to the shader
- if angle is not None and angle >= 0 and angle <= 90:
- self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle)))
+ if self._support_angle is not None and self._support_angle >= 0 and self._support_angle <= 90:
+ self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - self._support_angle)))
else:
self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang.
else:
@@ -112,6 +142,10 @@ class SolidView(View):
shade_factor * int(material_color[5:7], 16) / 255,
1.0
]
+
+ # Color the currently selected face-id. (Disable for now.)
+ #face = Selection.getHoverFace()
+ uniforms["hover_face"] = -1 #if not face or node != face[0] else face[1]
except ValueError:
pass
diff --git a/plugins/SolidView/plugin.json b/plugins/SolidView/plugin.json
index b3f62221c5..716f2d8d89 100644
--- a/plugins/SolidView/plugin.json
+++ b/plugins/SolidView/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides a normal solid mesh view.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py
index 0683c48635..35f597dcc5 100644
--- a/plugins/SupportEraser/SupportEraser.py
+++ b/plugins/SupportEraser/SupportEraser.py
@@ -98,8 +98,10 @@ class SupportEraser(Tool):
node.setName("Eraser")
node.setSelectable(True)
+ node.setCalculateBoundingBox(True)
mesh = self._createCube(10)
node.setMeshData(mesh.build())
+ node.calculateBoundingBoxMesh()
active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
node.addDecorator(BuildPlateDecorator(active_build_plate))
diff --git a/plugins/SupportEraser/plugin.json b/plugins/SupportEraser/plugin.json
index fa6d6d230e..888c3df50d 100644
--- a/plugins/SupportEraser/plugin.json
+++ b/plugins/SupportEraser/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Creates an eraser mesh to block the printing of support in certain places",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SupportEraser/tool_icon.svg b/plugins/SupportEraser/tool_icon.svg
index a0f8a3e3c3..fee69e0715 100644
--- a/plugins/SupportEraser/tool_icon.svg
+++ b/plugins/SupportEraser/tool_icon.svg
@@ -1,11 +1,14 @@
-
\ No newline at end of file
diff --git a/plugins/Toolbox/plugin.json b/plugins/Toolbox/plugin.json
index 61dc0429f5..0b967e1645 100644
--- a/plugins/Toolbox/plugin.json
+++ b/plugins/Toolbox/plugin.json
@@ -2,6 +2,6 @@
"name": "Toolbox",
"author": "Ultimaker B.V.",
"version": "1.0.1",
- "api": "6.0",
+ "api": "7.0",
"description": "Find, manage and install new Cura packages."
}
diff --git a/plugins/Toolbox/resources/qml/Toolbox.qml b/plugins/Toolbox/resources/qml/Toolbox.qml
index d15d98eed7..d6d862b5f6 100644
--- a/plugins/Toolbox/resources/qml/Toolbox.qml
+++ b/plugins/Toolbox/resources/qml/Toolbox.qml
@@ -1,11 +1,17 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
+// Main window for the Toolbox
+
import QtQuick 2.2
import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2
import UM 1.1 as UM
+import "./pages"
+import "./dialogs"
+import "./components"
+
Window
{
id: base
@@ -14,8 +20,8 @@ Window
modality: Qt.ApplicationModal
flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
- width: Math.floor(720 * screenScaleFactor)
- height: Math.floor(640 * screenScaleFactor)
+ width: UM.Theme.getSize("large_popup_dialog").width
+ height: UM.Theme.getSize("large_popup_dialog").height
minimumWidth: width
maximumWidth: minimumWidth
minimumHeight: height
@@ -29,9 +35,16 @@ Window
Item
{
anchors.fill: parent
+
+ WelcomePage
+ {
+ visible: toolbox.viewPage === "welcome"
+ }
+
ToolboxHeader
{
id: header
+ visible: toolbox.viewPage !== "welcome"
}
Item
@@ -48,32 +61,32 @@ Window
ToolboxLoadingPage
{
id: viewLoading
- visible: toolbox.viewCategory != "installed" && toolbox.viewPage == "loading"
+ visible: toolbox.viewCategory !== "installed" && toolbox.viewPage === "loading"
}
ToolboxErrorPage
{
id: viewErrored
- visible: toolbox.viewCategory != "installed" && toolbox.viewPage == "errored"
+ visible: toolbox.viewCategory !== "installed" && toolbox.viewPage === "errored"
}
ToolboxDownloadsPage
{
id: viewDownloads
- visible: toolbox.viewCategory != "installed" && toolbox.viewPage == "overview"
+ visible: toolbox.viewCategory !== "installed" && toolbox.viewPage === "overview"
}
ToolboxDetailPage
{
id: viewDetail
- visible: toolbox.viewCategory != "installed" && toolbox.viewPage == "detail"
+ visible: toolbox.viewCategory !== "installed" && toolbox.viewPage === "detail"
}
ToolboxAuthorPage
{
id: viewAuthor
- visible: toolbox.viewCategory != "installed" && toolbox.viewPage == "author"
+ visible: toolbox.viewCategory !== "installed" && toolbox.viewPage === "author"
}
ToolboxInstalledPage
{
id: installedPluginList
- visible: toolbox.viewCategory == "installed"
+ visible: toolbox.viewCategory === "installed"
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml b/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml
deleted file mode 100644
index 4d4ae92e73..0000000000
--- a/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2018 Ultimaker B.V.
-// Toolbox is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.2
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
-import UM 1.1 as UM
-import Cura 1.0 as Cura
-
-
-Item
-{
- id: base
-
- property var active: false
- property var complete: false
-
- property var readyLabel: catalog.i18nc("@action:button", "Install")
- property var activeLabel: catalog.i18nc("@action:button", "Cancel")
- property var completeLabel: catalog.i18nc("@action:button", "Installed")
-
- signal readyAction() // Action when button is ready and clicked (likely install)
- signal activeAction() // Action when button is active and clicked (likely cancel)
- signal completeAction() // Action when button is complete and clicked (likely go to installed)
-
- width: UM.Theme.getSize("toolbox_action_button").width
- height: UM.Theme.getSize("toolbox_action_button").height
-
- Cura.PrimaryButton
- {
- id: button
- width: UM.Theme.getSize("toolbox_action_button").width
- height: UM.Theme.getSize("toolbox_action_button").height
- fixedWidthMode: true
- text:
- {
- if (complete)
- {
- return completeLabel
- }
- else if (active)
- {
- return activeLabel
- }
- else
- {
- return readyLabel
- }
- }
- onClicked:
- {
- if (complete)
- {
- completeAction()
- }
- else if (active)
- {
- activeAction()
- }
- else
- {
- readyAction()
- }
- }
- busy: active
- }
-}
diff --git a/plugins/Toolbox/resources/qml/RatingWidget.qml b/plugins/Toolbox/resources/qml/components/RatingWidget.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/RatingWidget.qml
rename to plugins/Toolbox/resources/qml/components/RatingWidget.qml
diff --git a/plugins/Toolbox/resources/qml/SmallRatingWidget.qml b/plugins/Toolbox/resources/qml/components/SmallRatingWidget.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/SmallRatingWidget.qml
rename to plugins/Toolbox/resources/qml/components/SmallRatingWidget.qml
diff --git a/plugins/Toolbox/resources/qml/ToolboxActionButtonStyle.qml b/plugins/Toolbox/resources/qml/components/ToolboxActionButtonStyle.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/ToolboxActionButtonStyle.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxActionButtonStyle.qml
diff --git a/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml b/plugins/Toolbox/resources/qml/components/ToolboxBackColumn.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/ToolboxBackColumn.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxBackColumn.qml
diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/components/ToolboxCompatibilityChart.qml
similarity index 73%
rename from plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxCompatibilityChart.qml
index db4e8c628f..ae9241f0ab 100644
--- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxCompatibilityChart.qml
@@ -1,9 +1,9 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+
import UM 1.1 as UM
Item
@@ -11,48 +11,17 @@ Item
id: base
property var packageData
- property var technicalDataSheetUrl:
- {
- var link = undefined
- if ("Technical Data Sheet" in packageData.links)
- {
- // HACK: This is the way the old API (used in 3.6-beta) used to do it. For safety it's still here,
- // but it can be removed over time.
- link = packageData.links["Technical Data Sheet"]
- }
- else if ("technicalDataSheet" in packageData.links)
- {
- link = packageData.links["technicalDataSheet"]
- }
- return link
- }
- property var safetyDataSheetUrl:
- {
- var sds_name = "safetyDataSheet"
- return (sds_name in packageData.links) ? packageData.links[sds_name] : undefined
- }
- property var printingGuidelinesUrl:
- {
- var pg_name = "printingGuidelines"
- return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
- }
+ property var technicalDataSheetUrl: packageData.links.technicalDataSheet
+ property var safetyDataSheetUrl: packageData.links.safetyDataSheet
+ property var printingGuidelinesUrl: packageData.links.printingGuidelines
+ property var materialWebsiteUrl: packageData.links.website
- property var materialWebsiteUrl:
- {
- var pg_name = "website"
- return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
- }
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- height: visible ? childrenRect.height : 0
+ height: childrenRect.height
+ onVisibleChanged: packageData.type === "material" && (compatibilityItem.visible || dataSheetLinks.visible)
- visible: packageData.type == "material" &&
- (packageData.has_configs || technicalDataSheetUrl !== undefined ||
- safetyDataSheetUrl !== undefined || printingGuidelinesUrl !== undefined ||
- materialWebsiteUrl !== undefined)
-
- Item
+ Column
{
- id: combatibilityItem
+ id: compatibilityItem
visible: packageData.has_configs
width: parent.width
// This is a bit of a hack, but the whole QML is pretty messy right now. This needs a big overhaul.
@@ -61,7 +30,6 @@ Item
Label
{
id: heading
- anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
text: catalog.i18nc("@label", "Compatibility")
wrapMode: Text.WordWrap
@@ -73,8 +41,6 @@ Item
TableView
{
id: table
- anchors.top: heading.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
frameVisible: false
@@ -155,32 +121,32 @@ Item
TableViewColumn
{
role: "machine"
- title: "Machine"
+ title: catalog.i18nc("@label:table_header", "Machine")
width: Math.floor(table.width * 0.25)
delegate: columnTextDelegate
}
TableViewColumn
{
role: "print_core"
- title: "Print Core"
+ title: "Print Core" //This term should not be translated.
width: Math.floor(table.width * 0.2)
}
TableViewColumn
{
role: "build_plate"
- title: "Build Plate"
+ title: catalog.i18nc("@label:table_header", "Build Plate")
width: Math.floor(table.width * 0.225)
}
TableViewColumn
{
role: "support_material"
- title: "Support"
+ title: catalog.i18nc("@label:table_header", "Support")
width: Math.floor(table.width * 0.225)
}
TableViewColumn
{
role: "quality"
- title: "Quality"
+ title: catalog.i18nc("@label:table_header", "Quality")
width: Math.floor(table.width * 0.1)
}
}
@@ -188,13 +154,14 @@ Item
Label
{
- id: data_sheet_links
- anchors.top: combatibilityItem.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height / 2
+ id: dataSheetLinks
+ anchors.top: compatibilityItem.bottom
+ anchors.topMargin: UM.Theme.getSize("narrow_margin").height
visible: base.technicalDataSheetUrl !== undefined ||
- base.safetyDataSheetUrl !== undefined || base.printingGuidelinesUrl !== undefined ||
- base.materialWebsiteUrl !== undefined
- height: visible ? contentHeight : 0
+ base.safetyDataSheetUrl !== undefined ||
+ base.printingGuidelinesUrl !== undefined ||
+ base.materialWebsiteUrl !== undefined
+
text:
{
var result = ""
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml b/plugins/Toolbox/resources/qml/components/ToolboxDetailList.qml
similarity index 82%
rename from plugins/Toolbox/resources/qml/ToolboxDetailList.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDetailList.qml
index 4e44ea7d0b..22c6b6045f 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDetailList.qml
@@ -1,9 +1,8 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+import QtQuick 2.10
+import QtQuick.Controls 2.3
import UM 1.1 as UM
Item
@@ -11,10 +10,9 @@ Item
id: detailList
ScrollView
{
- frameVisible: false
+ clip: true
anchors.fill: detailList
- style: UM.Theme.styles.scrollview
- flickableItem.flickableDirection: Flickable.VerticalFlick
+
Column
{
anchors
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml b/plugins/Toolbox/resources/qml/components/ToolboxDetailTile.qml
similarity index 72%
rename from plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDetailTile.qml
index c7bb1f60ac..5badc6b66d 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDetailTile.qml
@@ -1,30 +1,30 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls 2.3
+
import UM 1.1 as UM
Item
{
id: tile
width: detailList.width - UM.Theme.getSize("wide_margin").width
- height: normalData.height + compatibilityChart.height + 4 * UM.Theme.getSize("default_margin").height
- Item
+ height: normalData.height + 2 * UM.Theme.getSize("wide_margin").height
+ Column
{
id: normalData
- height: childrenRect.height
+
anchors
{
+ top: parent.top
left: parent.left
right: controls.left
- rightMargin: UM.Theme.getSize("default_margin").width * 2 + UM.Theme.getSize("toolbox_loader").width
- top: parent.top
+ rightMargin: UM.Theme.getSize("wide_margin").width
}
+
Label
{
- id: packageName
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
text: model.name
@@ -33,9 +33,9 @@ Item
font: UM.Theme.getFont("medium_bold")
renderType: Text.NativeRendering
}
+
Label
{
- anchors.top: packageName.bottom
width: parent.width
text: model.description
maximumLineCount: 25
@@ -45,6 +45,12 @@ Item
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
}
+
+ ToolboxCompatibilityChart
+ {
+ width: parent.width
+ packageData: model
+ }
}
ToolboxDetailTileActions
@@ -57,20 +63,12 @@ Item
packageData: model
}
- ToolboxCompatibilityChart
- {
- id: compatibilityChart
- anchors.top: normalData.bottom
- width: normalData.width
- packageData: model
- }
-
Rectangle
{
color: UM.Theme.getColor("lining")
width: tile.width
height: UM.Theme.getSize("default_lining").height
- anchors.top: compatibilityChart.bottom
+ anchors.top: normalData.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height + UM.Theme.getSize("wide_margin").height //Normal margin for spacing after chart, wide margin between items.
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml b/plugins/Toolbox/resources/qml/components/ToolboxDetailTileActions.qml
similarity index 93%
rename from plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDetailTileActions.qml
index 60fe095537..dfe91edbf6 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDetailTileActions.qml
@@ -10,7 +10,7 @@ import Cura 1.1 as Cura
Column
{
property bool installed: toolbox.isInstalled(model.id)
- property bool canUpdate: toolbox.canUpdate(model.id)
+ property bool canUpdate: CuraApplication.getPackageManager().packagesWithUpdate.indexOf(model.id) != -1
property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn
property var packageData
@@ -35,11 +35,12 @@ Column
// Don't allow installing while another download is running
enabled: installed || (!(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired)
opacity: enabled ? 1.0 : 0.5
- visible: !updateButton.visible && !installed// Don't show when the update button is visible
+ visible: !updateButton.visible && !installed // Don't show when the update button is visible
}
Cura.SecondaryButton
{
+ id: installedButton
visible: installed
onClicked: toolbox.viewCategory = "installed"
text: catalog.i18nc("@action:button", "Installed")
@@ -112,11 +113,9 @@ Column
{
target: toolbox
onInstallChanged: installed = toolbox.isInstalled(model.id)
- onMetadataChanged: canUpdate = toolbox.canUpdate(model.id)
onFilterChanged:
{
installed = toolbox.isInstalled(model.id)
- canUpdate = toolbox.canUpdate(model.id)
}
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsGrid.qml
similarity index 93%
rename from plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDownloadsGrid.qml
index a9fcb39b28..6682281a31 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsGrid.qml
@@ -2,9 +2,7 @@
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
-import QtQuick.Layouts 1.3
+import QtQuick.Controls 2.3
import UM 1.1 as UM
Column
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsGridTile.qml
similarity index 96%
rename from plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDownloadsGridTile.qml
index 7844a5c394..78cdf1562a 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsGridTile.qml
@@ -67,7 +67,7 @@ Item
width: UM.Theme.getSize("toolbox_thumbnail_small").width - UM.Theme.getSize("wide_margin").width
height: UM.Theme.getSize("toolbox_thumbnail_small").height - UM.Theme.getSize("wide_margin").width
fillMode: Image.PreserveAspectFit
- source: model.icon_url || "../images/logobot.svg"
+ source: model.icon_url || "../../images/logobot.svg"
mipmap: true
}
UM.RecolorImage
@@ -76,13 +76,13 @@ Item
height: (parent.height * 0.4) | 0
anchors
{
- bottom: parent.bottomcommi
+ bottom: parent.bottom
right: parent.right
}
sourceSize.height: height
visible: installedPackages != 0
color: (installedPackages >= packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
- source: "../images/installed_check.svg"
+ source: "../../images/installed_check.svg"
}
}
Item
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml
similarity index 95%
rename from plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml
index 795622cf82..72dd6f91a2 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml
@@ -14,7 +14,7 @@ Rectangle
Column
{
height: childrenRect.height + 2 * padding
- spacing: UM.Theme.getSize("toolbox_showcase_spacing").width
+ spacing: UM.Theme.getSize("default_margin").width
width: parent.width
padding: UM.Theme.getSize("wide_margin").height
Label
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcaseTile.qml
similarity index 97%
rename from plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcaseTile.qml
index 89348b18de..f6e32b2d84 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcaseTile.qml
@@ -23,7 +23,7 @@ Rectangle
height: UM.Theme.getSize("toolbox_thumbnail_large").height - 4 * UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("toolbox_thumbnail_large").height - 4 * UM.Theme.getSize("default_margin").height
fillMode: Image.PreserveAspectFit
- source: model.icon_url || "../images/logobot.svg"
+ source: model.icon_url || "../../images/logobot.svg"
mipmap: true
anchors
{
@@ -62,7 +62,7 @@ Rectangle
}
visible: installedPackages != 0
color: (installedPackages >= packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
- source: "../images/installed_check.svg"
+ source: "../../images/installed_check.svg"
}
SmallRatingWidget
diff --git a/plugins/Toolbox/resources/qml/ToolboxFooter.qml b/plugins/Toolbox/resources/qml/components/ToolboxFooter.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/ToolboxFooter.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxFooter.qml
diff --git a/plugins/Toolbox/resources/qml/ToolboxHeader.qml b/plugins/Toolbox/resources/qml/components/ToolboxHeader.qml
similarity index 75%
rename from plugins/Toolbox/resources/qml/ToolboxHeader.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxHeader.qml
index 087402d564..491567eb5f 100644
--- a/plugins/Toolbox/resources/qml/ToolboxHeader.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxHeader.qml
@@ -1,9 +1,11 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.2
+import QtQuick 2.10
import QtQuick.Controls 1.4
-import UM 1.1 as UM
+
+import UM 1.4 as UM
+import Cura 1.0 as Cura
Item
{
@@ -50,6 +52,7 @@ Item
}
}
}
+
ToolboxTabButton
{
id: installedTabButton
@@ -62,7 +65,25 @@ Item
rightMargin: UM.Theme.getSize("default_margin").width
}
onClicked: toolbox.viewCategory = "installed"
+ width: UM.Theme.getSize("toolbox_header_tab").width + marketplaceNotificationIcon.width - UM.Theme.getSize("default_margin").width
}
+
+ Cura.NotificationIcon
+ {
+ id: marketplaceNotificationIcon
+
+ visible: CuraApplication.getPackageManager().packagesWithUpdate.length > 0
+
+ anchors.right: installedTabButton.right
+ anchors.verticalCenter: installedTabButton.verticalCenter
+
+ labelText:
+ {
+ const itemCount = CuraApplication.getPackageManager().packagesWithUpdate.length
+ return itemCount > 9 ? "9+" : itemCount
+ }
+ }
+
ToolboxShadow
{
anchors.top: bar.bottom
diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml b/plugins/Toolbox/resources/qml/components/ToolboxInstalledTile.qml
similarity index 96%
rename from plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxInstalledTile.qml
index f50c3f3ac6..f85a1056b7 100644
--- a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxInstalledTile.qml
@@ -41,14 +41,13 @@ Item
Column
{
id: pluginInfo
- topPadding: Math.floor(UM.Theme.getSize("default_margin").height / 2)
+ topPadding: UM.Theme.getSize("narrow_margin").height
property var color: model.type === "plugin" && !isEnabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("text")
width: Math.floor(tileRow.width - (authorInfo.width + pluginActions.width + 2 * tileRow.spacing + ((disableButton.visible) ? disableButton.width + tileRow.spacing : 0)))
Label
{
text: model.name
width: parent.width
- height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
wrapMode: Text.WordWrap
font: UM.Theme.getFont("large_bold")
color: pluginInfo.color
diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml b/plugins/Toolbox/resources/qml/components/ToolboxInstalledTileActions.qml
similarity index 96%
rename from plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxInstalledTileActions.qml
index 61af84fbe5..db30b1caf5 100644
--- a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxInstalledTileActions.qml
@@ -10,7 +10,7 @@ import Cura 1.1 as Cura
Column
{
- property bool canUpdate: false
+ property bool canUpdate: CuraApplication.getPackageManager().packagesWithUpdate.indexOf(model.id) != -1
property bool canDowngrade: false
property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn
width: UM.Theme.getSize("toolbox_action_button").width
@@ -83,7 +83,6 @@ Column
target: toolbox
onMetadataChanged:
{
- canUpdate = toolbox.canUpdate(model.id)
canDowngrade = toolbox.canDowngrade(model.id)
}
}
diff --git a/plugins/Toolbox/resources/qml/components/ToolboxProgressButton.qml b/plugins/Toolbox/resources/qml/components/ToolboxProgressButton.qml
new file mode 100644
index 0000000000..40d6c1af47
--- /dev/null
+++ b/plugins/Toolbox/resources/qml/components/ToolboxProgressButton.qml
@@ -0,0 +1,60 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Toolbox is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+
+import UM 1.1 as UM
+import Cura 1.0 as Cura
+
+
+Cura.PrimaryButton
+{
+ id: button
+
+ property var active: false
+ property var complete: false
+
+ property var readyLabel: catalog.i18nc("@action:button", "Install")
+ property var activeLabel: catalog.i18nc("@action:button", "Cancel")
+ property var completeLabel: catalog.i18nc("@action:button", "Installed")
+
+ signal readyAction() // Action when button is ready and clicked (likely install)
+ signal activeAction() // Action when button is active and clicked (likely cancel)
+ signal completeAction() // Action when button is complete and clicked (likely go to installed)
+
+ width: UM.Theme.getSize("toolbox_action_button").width
+ height: UM.Theme.getSize("toolbox_action_button").height
+ fixedWidthMode: true
+ text:
+ {
+ if (complete)
+ {
+ return completeLabel
+ }
+ else if (active)
+ {
+ return activeLabel
+ }
+ else
+ {
+ return readyLabel
+ }
+ }
+ onClicked:
+ {
+ if (complete)
+ {
+ completeAction()
+ }
+ else if (active)
+ {
+ activeAction()
+ }
+ else
+ {
+ readyAction()
+ }
+ }
+ busy: active
+}
diff --git a/plugins/Toolbox/resources/qml/ToolboxShadow.qml b/plugins/Toolbox/resources/qml/components/ToolboxShadow.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/ToolboxShadow.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxShadow.qml
diff --git a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml b/plugins/Toolbox/resources/qml/components/ToolboxTabButton.qml
similarity index 50%
rename from plugins/Toolbox/resources/qml/ToolboxTabButton.qml
rename to plugins/Toolbox/resources/qml/components/ToolboxTabButton.qml
index 5e1aeaa636..7a7d2be48a 100644
--- a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml
+++ b/plugins/Toolbox/resources/qml/components/ToolboxTabButton.qml
@@ -9,14 +9,17 @@ Button
{
id: control
property bool active: false
- hoverEnabled: true
+
+ implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
+ implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
background: Item
{
- implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
- implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
+ id: backgroundItem
Rectangle
{
+ id: highlight
+
visible: control.active
color: UM.Theme.getColor("primary")
anchors.bottom: parent.bottom
@@ -24,28 +27,42 @@ Button
height: UM.Theme.getSize("toolbox_header_highlight").height
}
}
+
contentItem: Label
{
id: label
text: control.text
- color:
- {
- if(control.hovered)
- {
- return UM.Theme.getColor("toolbox_header_button_text_hovered");
- }
- if(control.active)
- {
- return UM.Theme.getColor("toolbox_header_button_text_active");
- }
- else
- {
- return UM.Theme.getColor("toolbox_header_button_text_inactive");
- }
- }
- font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
+ color: UM.Theme.getColor("toolbox_header_button_text_inactive")
+ font: UM.Theme.getFont("medium")
+
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
+
renderType: Text.NativeRendering
}
+
+ states:
+ [
+ State
+ {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges
+ {
+ target: label
+ font: UM.Theme.getFont("default_italic")
+ }
+ },
+ State
+ {
+ name: "active"
+ when: control.active
+ PropertyChanges
+ {
+ target: label
+ font: UM.Theme.getFont("medium_bold")
+ color: UM.Theme.getColor("action_button_text")
+ }
+ }
+ ]
}
\ No newline at end of file
diff --git a/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml b/plugins/Toolbox/resources/qml/dialogs/ToolboxConfirmUninstallResetDialog.qml
similarity index 94%
rename from plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml
rename to plugins/Toolbox/resources/qml/dialogs/ToolboxConfirmUninstallResetDialog.qml
index e238132680..1b5e4d1d46 100644
--- a/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml
+++ b/plugins/Toolbox/resources/qml/dialogs/ToolboxConfirmUninstallResetDialog.qml
@@ -14,7 +14,7 @@ import Cura 1.0 as Cura
UM.Dialog
{
- // This dialog asks the user whether he/she wants to open a project file as a project or import models.
+ // This dialog asks the user to confirm he/she wants to uninstall materials/pprofiles which are currently in use
id: base
title: catalog.i18nc("@title:window", "Confirm uninstall") + toolbox.pluginToUninstall
@@ -26,7 +26,7 @@ UM.Dialog
minimumWidth: 450 * screenScaleFactor
minimumHeight: 150 * screenScaleFactor
- modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal
+ modality: Qt.WindowModal
Column
{
diff --git a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml b/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml
similarity index 90%
rename from plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml
rename to plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml
index 40b22c268d..f7edde1fff 100644
--- a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml
+++ b/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml
@@ -30,7 +30,7 @@ UM.Dialog
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
- text: licenseDialog.pluginName + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?")
+ text: licenseDialog.pluginName + ": " + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?")
wrapMode: Text.Wrap
renderType: Text.NativeRendering
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml b/plugins/Toolbox/resources/qml/pages/ToolboxAuthorPage.qml
similarity index 94%
rename from plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml
rename to plugins/Toolbox/resources/qml/pages/ToolboxAuthorPage.qml
index b653f1a73b..d1abe48de1 100644
--- a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml
+++ b/plugins/Toolbox/resources/qml/pages/ToolboxAuthorPage.qml
@@ -6,6 +6,8 @@ import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
+import "../components"
+
Item
{
id: page
@@ -31,7 +33,7 @@ Item
width: UM.Theme.getSize("toolbox_thumbnail_medium").width
height: UM.Theme.getSize("toolbox_thumbnail_medium").height
fillMode: Image.PreserveAspectFit
- source: details.icon_url || "../images/logobot.svg"
+ source: details.icon_url || "../../images/logobot.svg"
mipmap: true
anchors
{
@@ -65,6 +67,7 @@ Item
{
id: description
text: details.description || ""
+ font: UM.Theme.getFont("default")
anchors
{
top: title.bottom
@@ -108,6 +111,8 @@ Item
top: description.bottom
left: properties.right
leftMargin: UM.Theme.getSize("default_margin").width
+ right: parent.right
+ rightMargin: UM.Theme.getSize("default_margin").width
topMargin: UM.Theme.getSize("default_margin").height
}
spacing: Math.floor(UM.Theme.getSize("narrow_margin").height)
@@ -122,6 +127,8 @@ Item
}
return ""
}
+ width: parent.width
+ elide: Text.ElideRight
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/pages/ToolboxDetailPage.qml
similarity index 98%
rename from plugins/Toolbox/resources/qml/ToolboxDetailPage.qml
rename to plugins/Toolbox/resources/qml/pages/ToolboxDetailPage.qml
index fef2732af9..6d34e23f42 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml
+++ b/plugins/Toolbox/resources/qml/pages/ToolboxDetailPage.qml
@@ -8,6 +8,8 @@ import UM 1.1 as UM
import Cura 1.1 as Cura
+import "../components"
+
Item
{
id: page
@@ -44,7 +46,7 @@ Item
{
anchors.fill: parent
fillMode: Image.PreserveAspectFit
- source: details === null ? "" : (details.icon_url || "../images/logobot.svg")
+ source: details === null ? "" : (details.icon_url || "../../images/logobot.svg")
mipmap: true
}
}
@@ -89,6 +91,7 @@ Item
Label
{
text: catalog.i18nc("@label", "Your rating") + ":"
+ visible: details.type == "plugin"
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml b/plugins/Toolbox/resources/qml/pages/ToolboxDownloadsPage.qml
similarity index 53%
rename from plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml
rename to plugins/Toolbox/resources/qml/pages/ToolboxDownloadsPage.qml
index 3e0dda4f4a..9be8cbe2b9 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml
+++ b/plugins/Toolbox/resources/qml/pages/ToolboxDownloadsPage.qml
@@ -1,25 +1,24 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+import QtQuick 2.10
+import QtQuick.Controls 2.3
import UM 1.1 as UM
+import "../components"
+
ScrollView
{
- frameVisible: false
+ clip: true
width: parent.width
height: parent.height
- style: UM.Theme.styles.scrollview
-
- flickableItem.flickableDirection: Flickable.VerticalFlick
+ contentHeight: mainColumn.height
Column
{
+ id: mainColumn
width: base.width
spacing: UM.Theme.getSize("default_margin").height
- height: childrenRect.height
ToolboxDownloadsShowcase
{
@@ -31,14 +30,14 @@ ScrollView
{
id: allPlugins
width: parent.width
- heading: toolbox.viewCategory == "material" ? catalog.i18nc("@label", "Community Contributions") : catalog.i18nc("@label", "Community Plugins")
- model: toolbox.viewCategory == "material" ? toolbox.materialsAvailableModel : toolbox.pluginsAvailableModel
+ heading: toolbox.viewCategory === "material" ? catalog.i18nc("@label", "Community Contributions") : catalog.i18nc("@label", "Community Plugins")
+ model: toolbox.viewCategory === "material" ? toolbox.materialsAvailableModel : toolbox.pluginsAvailableModel
}
ToolboxDownloadsGrid
{
id: genericMaterials
- visible: toolbox.viewCategory == "material"
+ visible: toolbox.viewCategory === "material"
width: parent.width
heading: catalog.i18nc("@label", "Generic Materials")
model: toolbox.materialsGenericModel
diff --git a/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml b/plugins/Toolbox/resources/qml/pages/ToolboxErrorPage.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/ToolboxErrorPage.qml
rename to plugins/Toolbox/resources/qml/pages/ToolboxErrorPage.qml
diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml b/plugins/Toolbox/resources/qml/pages/ToolboxInstalledPage.qml
similarity index 72%
rename from plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml
rename to plugins/Toolbox/resources/qml/pages/ToolboxInstalledPage.qml
index 0c43c67679..99590c712c 100644
--- a/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml
+++ b/plugins/Toolbox/resources/qml/pages/ToolboxInstalledPage.qml
@@ -1,50 +1,52 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
-import QtQuick.Dialogs 1.1
-import QtQuick.Window 2.2
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls 2.3
import UM 1.1 as UM
+import "../components"
+
ScrollView
{
id: page
- frameVisible: false
+ clip: true
width: parent.width
height: parent.height
- style: UM.Theme.styles.scrollview
- flickableItem.flickableDirection: Flickable.VerticalFlick
Column
{
+ width: page.width
spacing: UM.Theme.getSize("default_margin").height
+ padding: UM.Theme.getSize("wide_margin").width
visible: toolbox.pluginsInstalledModel.items.length > 0
- height: childrenRect.height + 4 * UM.Theme.getSize("default_margin").height
-
- anchors
- {
- right: parent.right
- left: parent.left
- margins: UM.Theme.getSize("default_margin").width
- top: parent.top
- }
+ height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height
Label
{
- width: page.width
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ margins: parent.padding
+ }
text: catalog.i18nc("@title:tab", "Plugins")
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("large")
renderType: Text.NativeRendering
}
+
Rectangle
{
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ margins: parent.padding
+ }
id: installedPlugins
color: "transparent"
- width: parent.width
height: childrenRect.height + UM.Theme.getSize("default_margin").width
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
@@ -65,8 +67,15 @@ ScrollView
}
}
}
+
Label
{
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ margins: parent.padding
+ }
text: catalog.i18nc("@title:tab", "Materials")
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
@@ -75,9 +84,14 @@ ScrollView
Rectangle
{
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ margins: parent.padding
+ }
id: installedMaterials
color: "transparent"
- width: parent.width
height: childrenRect.height + UM.Theme.getSize("default_margin").width
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
diff --git a/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml b/plugins/Toolbox/resources/qml/pages/ToolboxLoadingPage.qml
similarity index 100%
rename from plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml
rename to plugins/Toolbox/resources/qml/pages/ToolboxLoadingPage.qml
diff --git a/plugins/Toolbox/resources/qml/pages/WelcomePage.qml b/plugins/Toolbox/resources/qml/pages/WelcomePage.qml
new file mode 100644
index 0000000000..cbfdf8f402
--- /dev/null
+++ b/plugins/Toolbox/resources/qml/pages/WelcomePage.qml
@@ -0,0 +1,53 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.7
+import QtQuick.Controls 2.1
+import QtQuick.Window 2.2
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+Column
+{
+ id: welcomePage
+ spacing: UM.Theme.getSize("wide_margin").height
+ width: parent.width
+ height: childrenRect.height
+ anchors.centerIn: parent
+
+ Image
+ {
+ id: profileImage
+ fillMode: Image.PreserveAspectFit
+ source: "../../images/logobot.svg"
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.round(parent.width / 4)
+ }
+
+ Label
+ {
+ id: welcomeTextLabel
+ text: catalog.i18nc("@description", "Get plugins and materials verified by Ultimaker")
+ width: Math.round(parent.width / 2)
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ wrapMode: Label.WordWrap
+ renderType: Text.NativeRendering
+ }
+
+ Cura.PrimaryButton
+ {
+ id: loginButton
+ width: UM.Theme.getSize("account_button").width
+ height: UM.Theme.getSize("account_button").height
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: catalog.i18nc("@button", "Sign in")
+ onClicked: Cura.API.account.login()
+ fixedWidthMode: true
+ }
+}
+
diff --git a/plugins/Toolbox/src/AuthorsModel.py b/plugins/Toolbox/src/AuthorsModel.py
index 877f8256ee..7bfc58df04 100644
--- a/plugins/Toolbox/src/AuthorsModel.py
+++ b/plugins/Toolbox/src/AuthorsModel.py
@@ -53,7 +53,7 @@ class AuthorsModel(ListModel):
# Filter on all the key-word arguments.
for key, value in self._filter.items():
- if key is "package_types":
+ if key == "package_types":
key_filter = lambda item, value = value: value in item["package_types"] # type: ignore
elif "*" in value:
key_filter = lambda item, key = key, value = value: self._matchRegExp(item, key, value) # type: ignore
diff --git a/plugins/Toolbox/src/ConfigsModel.py b/plugins/Toolbox/src/ConfigsModel.py
index dd54d53d93..9ba65caaa4 100644
--- a/plugins/Toolbox/src/ConfigsModel.py
+++ b/plugins/Toolbox/src/ConfigsModel.py
@@ -1,11 +1,10 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import re
-from typing import Dict
from PyQt5.QtCore import Qt, pyqtProperty
from UM.Qt.ListModel import ListModel
+
## Model that holds supported configurations (for material/quality packages).
class ConfigsModel(ListModel):
def __init__(self, parent = None):
diff --git a/plugins/Toolbox/src/PackagesModel.py b/plugins/Toolbox/src/PackagesModel.py
index d94fdf6bb7..1cf87790bc 100644
--- a/plugins/Toolbox/src/PackagesModel.py
+++ b/plugins/Toolbox/src/PackagesModel.py
@@ -112,7 +112,7 @@ class PackagesModel(ListModel):
# Filter on all the key-word arguments.
for key, value in self._filter.items():
- if key is "tags":
+ if key == "tags":
key_filter = lambda item, v = value: v in item["tags"]
elif "*" in value:
key_filter = lambda candidate, k = key, v = value: self._matchRegExp(candidate, k, v)
diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py
index 7d8d359831..27197275b8 100644
--- a/plugins/Toolbox/src/Toolbox.py
+++ b/plugins/Toolbox/src/Toolbox.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Toolbox is released under the terms of the LGPLv3 or higher.
import json
@@ -19,6 +19,7 @@ from UM.Version import Version
from cura import ApplicationMetadata
from cura import UltimakerCloudAuthentication
from cura.CuraApplication import CuraApplication
+from cura.Machines.ContainerTree import ContainerTree
from .AuthorsModel import AuthorsModel
from .PackagesModel import PackagesModel
@@ -47,10 +48,9 @@ class Toolbox(QObject, Extension):
self._download_progress = 0 # type: float
self._is_downloading = False # type: bool
self._network_manager = None # type: Optional[QNetworkAccessManager]
- self._request_headers = [] # type: List[Tuple[bytes, bytes]]
+ self._request_headers = [] # type: List[Tuple[bytes, bytes]]
self._updateRequestHeader()
-
self._request_urls = {} # type: Dict[str, QUrl]
self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated
self._old_plugin_ids = set() # type: Set[str]
@@ -59,13 +59,15 @@ class Toolbox(QObject, Extension):
# The responses as given by the server parsed to a list.
self._server_response_data = {
"authors": [],
- "packages": []
+ "packages": [],
+ "updates": [],
} # type: Dict[str, List[Any]]
# Models:
self._models = {
"authors": AuthorsModel(self),
"packages": PackagesModel(self),
+ "updates": PackagesModel(self),
} # type: Dict[str, Union[AuthorsModel, PackagesModel]]
self._plugins_showcase_model = PackagesModel(self)
@@ -86,7 +88,7 @@ class Toolbox(QObject, Extension):
# View page defines which type of page layout to use. For example,
# possible values include "overview", "detail" or "author".
- self._view_page = "loading" # type: str
+ self._view_page = "welcome" # type: str
# Active package refers to which package is currently being downloaded,
# installed, or otherwise modified.
@@ -105,7 +107,7 @@ class Toolbox(QObject, Extension):
self._restart_dialog_message = "" # type: str
self._application.initializationFinished.connect(self._onAppInitialized)
- self._application.getCuraAPI().account.loginStateChanged.connect(self._updateRequestHeader)
+ self._application.getCuraAPI().account.accessTokenChanged.connect(self._updateRequestHeader)
# Signals:
# --------------------------------------------------------------------------
@@ -125,6 +127,16 @@ class Toolbox(QObject, Extension):
showLicenseDialog = pyqtSignal()
uninstallVariablesChanged = pyqtSignal()
+ ## Go back to the start state (welcome screen or loading if no login required)
+ def _restart(self):
+ self._updateRequestHeader()
+ # For an Essentials build, login is mandatory
+ if not self._application.getCuraAPI().account.isLoggedIn and ApplicationMetadata.IsEnterpriseVersion:
+ self.setViewPage("welcome")
+ else:
+ self.setViewPage("loading")
+ self._fetchPackageData()
+
def _updateRequestHeader(self):
self._request_headers = [
(b"User-Agent",
@@ -185,16 +197,27 @@ class Toolbox(QObject, Extension):
cloud_api_version = self._cloud_api_version,
sdk_version = self._sdk_version
)
+
+ # We need to construct a query like installed_packages=ID:VERSION&installed_packages=ID:VERSION, etc.
+ installed_package_ids_with_versions = [":".join(items) for items in
+ self._package_manager.getAllInstalledPackageIdsAndVersions()]
+ installed_packages_query = "&installed_packages=".join(installed_package_ids_with_versions)
+
self._request_urls = {
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
- "packages": QUrl("{base_url}/packages".format(base_url = self._api_url))
+ "packages": QUrl("{base_url}/packages".format(base_url = self._api_url)),
+ "updates": QUrl("{base_url}/packages/package-updates?installed_packages={query}".format(
+ base_url = self._api_url, query = installed_packages_query))
}
- @pyqtSlot()
- def browsePackages(self) -> None:
- # Create the network manager:
- # This was formerly its own function but really had no reason to be as
- # it was never called more than once ever.
+ self._application.getCuraAPI().account.loginStateChanged.connect(self._restart)
+
+ # On boot we check which packages have updates.
+ if CuraApplication.getInstance().getPreferences().getValue("info/automatic_update_check") and len(installed_package_ids_with_versions) > 0:
+ # Request the latest and greatest!
+ self._fetchPackageUpdates()
+
+ def _prepareNetworkManager(self):
if self._network_manager is not None:
self._network_manager.finished.disconnect(self._onRequestFinished)
self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccessibleChanged)
@@ -202,13 +225,22 @@ class Toolbox(QObject, Extension):
self._network_manager.finished.connect(self._onRequestFinished)
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccessibleChanged)
+ def _fetchPackageUpdates(self):
+ self._prepareNetworkManager()
+ self._makeRequestByType("updates")
+
+ def _fetchPackageData(self):
+ self._prepareNetworkManager()
# Make remote requests:
self._makeRequestByType("packages")
self._makeRequestByType("authors")
-
# Gather installed packages:
self._updateInstalledModels()
+ # Displays the toolbox
+ @pyqtSlot()
+ def launch(self) -> None:
+
if not self._dialog:
self._dialog = self._createDialog("Toolbox.qml")
@@ -216,6 +248,8 @@ class Toolbox(QObject, Extension):
Logger.log("e", "Unexpected error trying to create the 'Marketplace' dialog.")
return
+ self._restart()
+
self._dialog.show()
# Apply enabled/disabled state to installed plugins
@@ -227,7 +261,7 @@ class Toolbox(QObject, Extension):
if not plugin_path:
return None
path = os.path.join(plugin_path, "resources", "qml", qml_name)
-
+
dialog = self._application.createQmlComponent(path, {"toolbox": self})
if not dialog:
raise Exception("Failed to create Marketplace dialog")
@@ -272,7 +306,7 @@ class Toolbox(QObject, Extension):
for plugin_id in old_plugin_ids:
# Neither the installed packages nor the packages that are scheduled to remove are old plugins
if plugin_id not in installed_package_ids and plugin_id not in scheduled_to_remove_package_ids:
- Logger.log("i", "Found a plugin that was installed with the old plugin browser: %s", plugin_id)
+ Logger.log("d", "Found a plugin that was installed with the old plugin browser: %s", plugin_id)
old_metadata = self._plugin_registry.getMetaData(plugin_id)
new_metadata = self._convertPluginMetadata(old_metadata)
@@ -321,7 +355,7 @@ class Toolbox(QObject, Extension):
self._package_used_qualities = package_used_qualities
# Ask change to default material / profile
if self._confirm_reset_dialog is None:
- self._confirm_reset_dialog = self._createDialog("ToolboxConfirmUninstallResetDialog.qml")
+ self._confirm_reset_dialog = self._createDialog("dialogs/ToolboxConfirmUninstallResetDialog.qml")
self.uninstallVariablesChanged.emit()
if self._confirm_reset_dialog is None:
Logger.log("e", "ToolboxConfirmUninstallResetDialog should have been initialized, but it is not. Not showing dialog and not uninstalling package.")
@@ -353,15 +387,22 @@ class Toolbox(QObject, Extension):
@pyqtSlot()
def resetMaterialsQualitiesAndUninstall(self) -> None:
application = CuraApplication.getInstance()
- material_manager = application.getMaterialManager()
- quality_manager = application.getQualityManager()
machine_manager = application.getMachineManager()
+ container_tree = ContainerTree.getInstance()
for global_stack, extruder_nr, container_id in self._package_used_materials:
- default_material_node = material_manager.getDefaultMaterial(global_stack, extruder_nr, global_stack.extruders[extruder_nr].variant.getName())
+ extruder = global_stack.extruderList[int(extruder_nr)]
+ approximate_diameter = extruder.getApproximateMaterialDiameter()
+ variant_node = container_tree.machines[global_stack.definition.getId()].variants[extruder.variant.getName()]
+ default_material_node = variant_node.preferredMaterial(approximate_diameter)
machine_manager.setMaterial(extruder_nr, default_material_node, global_stack = global_stack)
for global_stack, extruder_nr, container_id in self._package_used_qualities:
- default_quality_group = quality_manager.getDefaultQualityType(global_stack)
+ variant_names = [extruder.variant.getName() for extruder in global_stack.extruderList]
+ material_bases = [extruder.material.getMetaDataEntry("base_file") for extruder in global_stack.extruderList]
+ extruder_enabled = [extruder.isEnabled for extruder in global_stack.extruderList]
+ definition_id = global_stack.definition.getId()
+ machine_node = container_tree.machines[definition_id]
+ default_quality_group = machine_node.getQualityGroups(variant_names, material_bases, extruder_enabled)[machine_node.preferred_quality_type]
machine_manager.setQualityGroup(default_quality_group, global_stack = global_stack)
if self._package_id_to_uninstall is not None:
@@ -455,36 +496,6 @@ class Toolbox(QObject, Extension):
break
return remote_package
- # Checks
- # --------------------------------------------------------------------------
- @pyqtSlot(str, result = bool)
- def canUpdate(self, package_id: str) -> bool:
- local_package = self._package_manager.getInstalledPackageInfo(package_id)
- if local_package is None:
- local_package = self.getOldPluginPackageMetadata(package_id)
- if local_package is None:
- return False
-
- remote_package = self.getRemotePackage(package_id)
- if remote_package is None:
- return False
-
- local_version = Version(local_package["package_version"])
- remote_version = Version(remote_package["package_version"])
- can_upgrade = False
- if remote_version > local_version:
- can_upgrade = True
- # A package with the same version can be built to have different SDK versions. So, for a package with the same
- # version, we also need to check if the current one has a lower SDK version. If so, this package should also
- # be upgradable.
- elif remote_version == local_version:
- # First read sdk_version_semver. If that doesn't exist, read just sdk_version (old version system).
- remote_sdk_version = Version(remote_package.get("sdk_version_semver", remote_package.get("sdk_version", 0)))
- local_sdk_version = Version(local_package.get("sdk_version_semver", local_package.get("sdk_version", 0)))
- can_upgrade = local_sdk_version < remote_sdk_version
-
- return can_upgrade
-
@pyqtSlot(str, result = bool)
def canDowngrade(self, package_id: str) -> bool:
# If the currently installed version is higher than the bundled version (if present), the we can downgrade
@@ -550,7 +561,7 @@ class Toolbox(QObject, Extension):
# Make API Calls
# --------------------------------------------------------------------------
def _makeRequestByType(self, request_type: str) -> None:
- Logger.log("i", "Requesting %s metadata from server.", request_type)
+ Logger.log("d", "Requesting %s metadata from server.", request_type)
request = QNetworkRequest(self._request_urls[request_type])
for header_name, header_value in self._request_headers:
request.setRawHeader(header_name, header_value)
@@ -584,9 +595,15 @@ class Toolbox(QObject, Extension):
if self._download_reply:
try:
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
- except TypeError: # Raised when the method is not connected to the signal yet.
+ except (TypeError, RuntimeError): # Raised when the method is not connected to the signal yet.
pass # Don't need to disconnect.
- self._download_reply.abort()
+ try:
+ self._download_reply.abort()
+ except RuntimeError:
+ # In some cases the garbage collector is a bit to agressive, which causes the dowload_reply
+ # to be deleted (especially if the machine has been put to sleep). As we don't know what exactly causes
+ # this (The issue probably lives in the bowels of (py)Qt somewhere), we can only catch and ignore it.
+ pass
self._download_reply = None
self._download_request = None
self.setDownloadProgress(0)
@@ -628,17 +645,22 @@ class Toolbox(QObject, Extension):
if not self._models[response_type]:
Logger.log("e", "Could not find the %s model.", response_type)
break
-
+
self._server_response_data[response_type] = json_data["data"]
self._models[response_type].setMetadata(self._server_response_data[response_type])
- if response_type is "packages":
+ if response_type == "packages":
self._models[response_type].setFilter({"type": "plugin"})
self.reBuildMaterialsModels()
self.reBuildPluginsModels()
- elif response_type is "authors":
+ self._notifyPackageManager()
+ elif response_type == "authors":
self._models[response_type].setFilter({"package_types": "material"})
self._models[response_type].setFilter({"tags": "generic"})
+ elif response_type == "updates":
+ # Tell the package manager that there's a new set of updates available.
+ packages = set([pkg["package_id"] for pkg in self._server_response_data[response_type]])
+ self._package_manager.setPackagesWithUpdate(packages)
self.metadataChanged.emit()
@@ -656,6 +678,11 @@ class Toolbox(QObject, Extension):
# Ignore any operation that is not a get operation
pass
+ # This function goes through all known remote versions of a package and notifies the package manager of this change
+ def _notifyPackageManager(self):
+ for package in self._server_response_data["packages"]:
+ self._package_manager.addAvailablePackageVersion(package["package_id"], Version(package["package_version"]))
+
def _onDownloadProgress(self, bytes_sent: int, bytes_total: int) -> None:
if bytes_total > 0:
new_progress = bytes_sent / bytes_total * 100
@@ -664,11 +691,15 @@ class Toolbox(QObject, Extension):
self.setIsDownloading(False)
self._download_reply = cast(QNetworkReply, self._download_reply)
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
-
+
# Check if the download was sucessfull
if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
- Logger.log("w", "Failed to download package. The following error was returned: %s", json.loads(bytes(self._download_reply.readAll()).decode("utf-8")))
- return
+ try:
+ Logger.log("w", "Failed to download package. The following error was returned: %s", json.loads(bytes(self._download_reply.readAll()).decode("utf-8")))
+ except json.decoder.JSONDecodeError:
+ Logger.logException("w", "Failed to download package and failed to parse a response from it")
+ finally:
+ return
# Must not delete the temporary file on Windows
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False)
file_path = self._temp_plugin_file.name
diff --git a/plugins/TrimeshReader/TrimeshReader.py b/plugins/TrimeshReader/TrimeshReader.py
new file mode 100644
index 0000000000..91f8423579
--- /dev/null
+++ b/plugins/TrimeshReader/TrimeshReader.py
@@ -0,0 +1,161 @@
+# Copyright (c) 2019 Ultimaker B.V., fieldOfView
+# Cura is released under the terms of the LGPLv3 or higher.
+
+# The _toMeshData function is taken from the AMFReader class which was built by fieldOfView.
+
+from typing import Any, List, Union, TYPE_CHECKING
+import numpy # To create the mesh data.
+import os.path # To create the mesh name for the resulting mesh.
+import trimesh # To load the files into a Trimesh.
+
+from UM.Mesh.MeshData import MeshData, calculateNormalsFromIndexedVertices # To construct meshes from the Trimesh data.
+from UM.Mesh.MeshReader import MeshReader # The plug-in type we're extending.
+from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType # To add file types that we can open.
+from UM.Scene.GroupDecorator import GroupDecorator # Added to the parent node if we load multiple nodes at once.
+
+from cura.CuraApplication import CuraApplication
+from cura.Scene.BuildPlateDecorator import BuildPlateDecorator # Added to the resulting scene node.
+from cura.Scene.ConvexHullDecorator import ConvexHullDecorator # Added to group nodes if we load multiple nodes at once.
+from cura.Scene.CuraSceneNode import CuraSceneNode # To create a node in the scene after reading the file.
+from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator # Added to the resulting scene node.
+
+if TYPE_CHECKING:
+ from UM.Scene.SceneNode import SceneNode
+
+## Class that leverages Trimesh to import files.
+class TrimeshReader(MeshReader):
+ def __init__(self) -> None:
+ super().__init__()
+
+ self._supported_extensions = [".ctm", ".dae", ".gltf", ".glb", ".ply", ".zae"]
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "application/x-ctm",
+ comment = "Open Compressed Triangle Mesh",
+ suffixes = ["ctm"]
+ )
+ )
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "model/vnd.collada+xml",
+ comment = "COLLADA Digital Asset Exchange",
+ suffixes = ["dae"]
+ )
+ )
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "model/gltf-binary",
+ comment = "glTF Binary",
+ suffixes = ["glb"]
+ )
+ )
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "model/gltf+json",
+ comment = "glTF Embedded JSON",
+ suffixes = ["gltf"]
+ )
+ )
+ # Trimesh seems to have a bug when reading .off files.
+ #MimeTypeDatabase.addMimeType(
+ # MimeType(
+ # name = "application/x-off",
+ # comment = "Geomview Object File Format",
+ # suffixes = ["off"]
+ # )
+ #)
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "application/x-ply", # Wikipedia lists the MIME type as "text/plain" but that won't do as it's not unique to PLY files.
+ comment = "Stanford Triangle Format",
+ suffixes = ["ply"]
+ )
+ )
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "model/vnd.collada+xml+zip",
+ comment = "Compressed COLLADA Digital Asset Exchange",
+ suffixes = ["zae"]
+ )
+ )
+
+ ## Reads a file using Trimesh.
+ # \param file_name The file path. This is assumed to be one of the file
+ # types that Trimesh can read. It will not be checked again.
+ # \return A scene node that contains the file's contents.
+ def _read(self, file_name: str) -> Union["SceneNode", List["SceneNode"]]:
+ # CURA-6739
+ # GLTF files are essentially JSON files. If you directly give a file name to trimesh.load(), it will
+ # try to figure out the format, but for GLTF, it loads it as a binary file with flags "rb", and the json.load()
+ # doesn't like it. For some reason, this seems to happen with 3.5.7, but not 3.7.1. Below is a workaround to
+ # pass a file object that has been opened with "r" instead "rb" to load a GLTF file.
+ if file_name.lower().endswith(".gltf"):
+ mesh_or_scene = trimesh.load(open(file_name, "r", encoding = "utf-8"), file_type = "gltf")
+ else:
+ mesh_or_scene = trimesh.load(file_name)
+
+ meshes = [] # type: List[Union[trimesh.Trimesh, trimesh.Scene, Any]]
+ if isinstance(mesh_or_scene, trimesh.Trimesh):
+ meshes = [mesh_or_scene]
+ elif isinstance(mesh_or_scene, trimesh.Scene):
+ meshes = [mesh for mesh in mesh_or_scene.geometry.values()]
+
+ active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
+ nodes = [] # type: List[SceneNode]
+ for mesh in meshes:
+ if not isinstance(mesh, trimesh.Trimesh): # Trimesh can also receive point clouds, 2D paths, 3D paths or metadata. Skip those.
+ continue
+ mesh.merge_vertices()
+ mesh.remove_unreferenced_vertices()
+ mesh.fix_normals()
+ mesh_data = self._toMeshData(mesh)
+
+ file_base_name = os.path.basename(file_name)
+ new_node = CuraSceneNode()
+ new_node.setMeshData(mesh_data)
+ new_node.setSelectable(True)
+ new_node.setName(file_base_name if len(meshes) == 1 else "{file_base_name} {counter}".format(file_base_name = file_base_name, counter = str(len(nodes) + 1)))
+ new_node.addDecorator(BuildPlateDecorator(active_build_plate))
+ new_node.addDecorator(SliceableObjectDecorator())
+ nodes.append(new_node)
+
+ if len(nodes) == 1:
+ return nodes[0]
+ # Add all nodes to a group so they stay together.
+ group_node = CuraSceneNode()
+ group_node.addDecorator(GroupDecorator())
+ group_node.addDecorator(ConvexHullDecorator())
+ group_node.addDecorator(BuildPlateDecorator(active_build_plate))
+ for node in nodes:
+ node.setParent(group_node)
+ return group_node
+
+ ## Converts a Trimesh to Uranium's MeshData.
+ # \param tri_node A Trimesh containing the contents of a file that was
+ # just read.
+ # \return Mesh data from the Trimesh in a way that Uranium can understand
+ # it.
+ def _toMeshData(self, tri_node: trimesh.base.Trimesh) -> MeshData:
+ tri_faces = tri_node.faces
+ tri_vertices = tri_node.vertices
+
+ indices = []
+ vertices = []
+
+ index_count = 0
+ face_count = 0
+ for tri_face in tri_faces:
+ face = []
+ for tri_index in tri_face:
+ vertices.append(tri_vertices[tri_index])
+ face.append(index_count)
+ index_count += 1
+ indices.append(face)
+ face_count += 1
+
+ vertices = numpy.asarray(vertices, dtype = numpy.float32)
+ indices = numpy.asarray(indices, dtype = numpy.int32)
+ normals = calculateNormalsFromIndexedVertices(vertices, indices, face_count)
+
+ mesh_data = MeshData(vertices = vertices, indices = indices, normals = normals)
+ return mesh_data
\ No newline at end of file
diff --git a/plugins/TrimeshReader/__init__.py b/plugins/TrimeshReader/__init__.py
new file mode 100644
index 0000000000..8a267a7bc0
--- /dev/null
+++ b/plugins/TrimeshReader/__init__.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2019 Ultimaker
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from . import TrimeshReader
+
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("uranium")
+
+
+def getMetaData():
+ return {
+ "mesh_reader": [
+ {
+ "extension": "ctm",
+ "description": i18n_catalog.i18nc("@item:inlistbox 'Open' is part of the name of this file format.", "Open Compressed Triangle Mesh")
+ },
+ {
+ "extension": "dae",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "COLLADA Digital Asset Exchange")
+ },
+ {
+ "extension": "glb",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "glTF Binary")
+ },
+ {
+ "extension": "gltf",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "glTF Embedded JSON")
+ },
+ # Trimesh seems to have a bug when reading OFF files.
+ #{
+ # "extension": "off",
+ # "description": i18n_catalog.i18nc("@item:inlistbox", "Geomview Object File Format")
+ #},
+ {
+ "extension": "ply",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "Stanford Triangle Format")
+ },
+ {
+ "extension": "zae",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "Compressed COLLADA Digital Asset Exchange")
+ }
+ ]
+ }
+
+def register(app):
+ return {"mesh_reader": TrimeshReader.TrimeshReader()}
diff --git a/plugins/TrimeshReader/plugin.json b/plugins/TrimeshReader/plugin.json
new file mode 100644
index 0000000000..dbe937b01d
--- /dev/null
+++ b/plugins/TrimeshReader/plugin.json
@@ -0,0 +1,7 @@
+{
+ "name": "Trimesh Reader",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Provides support for reading model files.",
+ "api": "7.0.0"
+}
diff --git a/plugins/UFPReader/UFPReader.py b/plugins/UFPReader/UFPReader.py
new file mode 100644
index 0000000000..71061f938b
--- /dev/null
+++ b/plugins/UFPReader/UFPReader.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import TYPE_CHECKING
+
+from Charon.VirtualFile import VirtualFile
+
+from UM.Mesh.MeshReader import MeshReader
+from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
+from UM.PluginRegistry import PluginRegistry
+
+if TYPE_CHECKING:
+ from cura.Scene.CuraSceneNode import CuraSceneNode
+
+
+class UFPReader(MeshReader):
+
+ def __init__(self) -> None:
+ super().__init__()
+
+ MimeTypeDatabase.addMimeType(
+ MimeType(
+ name = "application/x-ufp",
+ comment = "Ultimaker Format Package",
+ suffixes = ["ufp"]
+ )
+ )
+ self._supported_extensions = [".ufp"]
+
+ def _read(self, file_name: str) -> "CuraSceneNode":
+ # Open the file
+ archive = VirtualFile()
+ archive.open(file_name)
+ # Get the gcode data from the file
+ gcode_data = archive.getData("/3D/model.gcode")
+ # Convert the bytes stream to string
+ gcode_stream = gcode_data["/3D/model.gcode"].decode("utf-8")
+
+ # Open the GCodeReader to parse the data
+ gcode_reader = PluginRegistry.getInstance().getPluginObject("GCodeReader") # type: ignore
+ gcode_reader.preReadFromStream(gcode_stream) # type: ignore
+ return gcode_reader.readFromStream(gcode_stream, file_name) # type: ignore
diff --git a/plugins/UFPReader/__init__.py b/plugins/UFPReader/__init__.py
new file mode 100644
index 0000000000..cfea4b9882
--- /dev/null
+++ b/plugins/UFPReader/__init__.py
@@ -0,0 +1,34 @@
+#Copyright (c) 2019 Ultimaker B.V.
+#Cura is released under the terms of the LGPLv3 or higher.
+
+import sys
+
+from UM.Logger import Logger
+try:
+ from . import UFPReader
+except ImportError:
+ Logger.log("w", "Could not import UFPReader; libCharon may be missing")
+
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("cura")
+
+
+def getMetaData():
+ return {
+ "mesh_reader": [
+ {
+ "mime_type": "application/x-ufp",
+ "extension": "ufp",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "Ultimaker Format Package")
+ }
+ ]
+ }
+
+
+def register(app):
+ if "UFPReader.UFPReader" not in sys.modules:
+ return {}
+
+ app.addNonSliceableExtension(".ufp")
+ return {"mesh_reader": UFPReader.UFPReader()}
+
diff --git a/plugins/UFPReader/plugin.json b/plugins/UFPReader/plugin.json
new file mode 100644
index 0000000000..a88a9c3ab0
--- /dev/null
+++ b/plugins/UFPReader/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "UFP Reader",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Provides support for reading Ultimaker Format Packages.",
+ "supported_sdk_versions": ["7.0.0"],
+ "i18n-catalog": "cura"
+}
\ No newline at end of file
diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py
index c0db104c82..e085adfd47 100644
--- a/plugins/UFPWriter/UFPWriter.py
+++ b/plugins/UFPWriter/UFPWriter.py
@@ -1,4 +1,4 @@
-#Copyright (c) 2018 Ultimaker B.V.
+#Copyright (c) 2019 Ultimaker B.V.
#Cura is released under the terms of the LGPLv3 or higher.
from typing import cast
@@ -7,13 +7,13 @@ from Charon.VirtualFile import VirtualFile #To open UFP files.
from Charon.OpenMode import OpenMode #To indicate that we want to write to UFP files.
from io import StringIO #For converting g-code to bytes.
-from UM.Application import Application
from UM.Logger import Logger
from UM.Mesh.MeshWriter import MeshWriter #The writer we need to implement.
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
from UM.PluginRegistry import PluginRegistry #To get the g-code writer.
from PyQt5.QtCore import QBuffer
+from cura.CuraApplication import CuraApplication
from cura.Snapshot import Snapshot
from cura.Utils.Threading import call_on_qt_thread
@@ -28,7 +28,7 @@ class UFPWriter(MeshWriter):
MimeTypeDatabase.addMimeType(
MimeType(
name = "application/x-ufp",
- comment = "Cura UFP File",
+ comment = "Ultimaker Format Package",
suffixes = ["ufp"]
)
)
@@ -38,7 +38,11 @@ class UFPWriter(MeshWriter):
def _createSnapshot(self, *args):
# must be called from the main thread because of OpenGL
Logger.log("d", "Creating thumbnail image...")
- self._snapshot = Snapshot.snapshot(width = 300, height = 300)
+ try:
+ self._snapshot = Snapshot.snapshot(width = 300, height = 300)
+ except Exception:
+ Logger.logException("w", "Failed to create snapshot image")
+ self._snapshot = None # Failing to create thumbnail should not fail creation of UFP
# This needs to be called on the main thread (Qt thread) because the serialization of material containers can
# trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the
@@ -79,9 +83,9 @@ class UFPWriter(MeshWriter):
Logger.log("d", "Thumbnail not created, cannot save it")
# Store the material.
- application = Application.getInstance()
+ application = CuraApplication.getInstance()
machine_manager = application.getMachineManager()
- material_manager = application.getMaterialManager()
+ container_registry = application.getContainerRegistry()
global_stack = machine_manager.activeMachine
material_extension = "xml.fdm_material"
@@ -107,12 +111,12 @@ class UFPWriter(MeshWriter):
continue
material_root_id = material.getMetaDataEntry("base_file")
- material_group = material_manager.getMaterialGroup(material_root_id)
- if material_group is None:
- Logger.log("e", "Cannot find material container with root id [%s]", material_root_id)
+ material_root_query = container_registry.findContainers(id = material_root_id)
+ if not material_root_query:
+ Logger.log("e", "Cannot find material container with root id {root_id}".format(root_id = material_root_id))
return False
+ material_container = material_root_query[0]
- material_container = material_group.root_material_node.getContainer()
try:
serialized_material = material_container.serialize()
except NotImplementedError:
diff --git a/plugins/UFPWriter/plugin.json b/plugins/UFPWriter/plugin.json
index 288d6acf77..35fd18f05e 100644
--- a/plugins/UFPWriter/plugin.json
+++ b/plugins/UFPWriter/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides support for writing Ultimaker Format Packages.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/__init__.py b/plugins/UM3NetworkPrinting/__init__.py
index 3da7795589..ea0f69639d 100644
--- a/plugins/UM3NetworkPrinting/__init__.py
+++ b/plugins/UM3NetworkPrinting/__init__.py
@@ -1,7 +1,7 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from .src import DiscoverUM3Action
from .src import UM3OutputDevicePlugin
+from .src import UltimakerNetworkedPrinterAction
def getMetaData():
@@ -11,5 +11,5 @@ def getMetaData():
def register(app):
return {
"output_device": UM3OutputDevicePlugin.UM3OutputDevicePlugin(),
- "machine_action": DiscoverUM3Action.DiscoverUM3Action()
+ "machine_action": UltimakerNetworkedPrinterAction.UltimakerNetworkedPrinterAction()
}
diff --git a/plugins/UM3NetworkPrinting/plugin.json b/plugins/UM3NetworkPrinting/plugin.json
index 088b4dae6a..193ba63d83 100644
--- a/plugins/UM3NetworkPrinting/plugin.json
+++ b/plugins/UM3NetworkPrinting/plugin.json
@@ -1,8 +1,8 @@
{
- "name": "UM3 Network Connection",
+ "name": "Ultimaker Network Connection",
"author": "Ultimaker B.V.",
- "description": "Manages network connections to Ultimaker 3 printers.",
- "version": "1.0.1",
- "api": "6.0",
+ "description": "Manages network connections to Ultimaker networked printers.",
+ "version": "2.0.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker S3.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S3.png
new file mode 100644
index 0000000000..b6ce6e1273
Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S3.png differ
diff --git a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml
index c0369cac0b..2e3d17ceb0 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -53,4 +53,4 @@ Rectangle
}
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml
index 3883a7e285..59a0148550 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml
@@ -1,8 +1,8 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import UM 1.2 as UM
-import Cura 1.0 as Cura
+import Cura 1.5 as Cura
import QtQuick 2.2
import QtQuick.Controls 1.1
@@ -14,42 +14,22 @@ Cura.MachineAction
{
id: base
anchors.fill: parent;
+ property alias currentItemIndex: listview.currentIndex
property var selectedDevice: null
property bool completeProperties: true
+ // For validating IP addresses
+ property var networkingUtil: Cura.NetworkingUtil {}
+
function connectToPrinter()
{
- if(base.selectedDevice && base.completeProperties)
+ if (base.selectedDevice && base.completeProperties)
{
- var printerKey = base.selectedDevice.key
- var printerName = base.selectedDevice.name // TODO To change when the groups have a name
- if (manager.getStoredKey() != printerKey)
- {
- // Check if there is another instance with the same key
- if (!manager.existsKey(printerKey))
- {
- manager.associateActiveMachineWithPrinterDevice(base.selectedDevice)
- manager.setGroupName(printerName) // TODO To change when the groups have a name
- completed()
- }
- else
- {
- existingConnectionDialog.open()
- }
- }
+ manager.associateActiveMachineWithPrinterDevice(base.selectedDevice)
+ completed()
}
}
- MessageDialog
- {
- id: existingConnectionDialog
- title: catalog.i18nc("@window:title", "Existing Connection")
- icon: StandardIcon.Information
- text: catalog.i18nc("@message:text", "This printer/group is already added to Cura. Please select another printer/group.")
- standardButtons: StandardButton.Ok
- modality: Qt.ApplicationModal
- }
-
Column
{
anchors.fill: parent;
@@ -74,7 +54,7 @@ Cura.MachineAction
width: parent.width
wrapMode: Text.WordWrap
renderType: Text.NativeRendering
- text: catalog.i18nc("@label", "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n\nSelect your printer from the list below:")
+ text: catalog.i18nc("@label", "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.") + "\n\n" + catalog.i18nc("@label", "Select your printer from the list below:")
}
Row
@@ -147,21 +127,6 @@ Cura.MachineAction
{
id: listview
model: manager.foundDevices
- onModelChanged:
- {
- var selectedKey = manager.getLastManualEntryKey()
- // If there is no last manual entry key, then we select the stored key (if any)
- if (selectedKey == "")
- selectedKey = manager.getStoredKey()
- for(var i = 0; i < model.length; i++) {
- if(model[i].key == selectedKey)
- {
- currentIndex = i;
- return
- }
- }
- currentIndex = -1;
- }
width: parent.width
currentIndex: -1
onCurrentIndexChanged:
@@ -246,29 +211,10 @@ Cura.MachineAction
renderType: Text.NativeRendering
text:
{
- if(base.selectedDevice)
- {
- if (base.selectedDevice.printerType == "ultimaker3")
- {
- return "Ultimaker 3";
- }
- else if (base.selectedDevice.printerType == "ultimaker3_extended")
- {
- return "Ultimaker 3 Extended";
- }
- else if (base.selectedDevice.printerType == "ultimaker_s5")
- {
- return "Ultimaker S5";
- }
- else
- {
- return catalog.i18nc("@label", "Unknown") // We have no idea what type it is. Should not happen 'in the field'
- }
- }
- else
- {
- return ""
+ if (base.selectedDevice) {
+ return base.selectedDevice.printerTypeName
}
+ return ""
}
}
Label
@@ -342,6 +288,17 @@ Cura.MachineAction
}
}
+ MessageDialog
+ {
+ id: invalidIPAddressMessageDialog
+ x: parent ? (parent.x + (parent.width) / 2) : 0
+ y: parent ? (parent.y + (parent.height) / 2) : 0
+ title: catalog.i18nc("@title:window", "Invalid IP address")
+ text: catalog.i18nc("@text", "Please enter a valid IP address.")
+ icon: StandardIcon.Warning
+ standardButtons: StandardButton.Ok
+ }
+
UM.Dialog
{
id: manualPrinterDialog
@@ -371,7 +328,7 @@ Cura.MachineAction
Label
{
- text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.")
+ text: catalog.i18nc("@label", "Enter the IP address of your printer on the network.")
width: parent.width
wrapMode: Text.WordWrap
renderType: Text.NativeRendering
@@ -404,6 +361,26 @@ Cura.MachineAction
text: catalog.i18nc("@action:button", "OK")
onClicked:
{
+ // Validate the input first
+ if (!networkingUtil.isValidIP(manualPrinterDialog.addressText))
+ {
+ invalidIPAddressMessageDialog.open()
+ return
+ }
+
+ // if the entered IP address has already been discovered, switch the current item to that item
+ // and do nothing else.
+ for (var i = 0; i < manager.foundDevices.length; i++)
+ {
+ var device = manager.foundDevices[i]
+ if (device.address == manualPrinterDialog.addressText)
+ {
+ currentItemIndex = i
+ manualPrinterDialog.hide()
+ return
+ }
+ }
+
manager.setManualDevice(manualPrinterDialog.printerKey, manualPrinterDialog.addressText)
manualPrinterDialog.hide()
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/ExpandableCard.qml b/plugins/UM3NetworkPrinting/resources/qml/ExpandableCard.qml
index fae8280488..5257361367 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/ExpandableCard.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/ExpandableCard.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -87,4 +87,4 @@ Item
}
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml b/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml
index 74d9377f3e..61981dab2c 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml
index d1a0c207c5..5d08422877 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -35,7 +35,7 @@ Item
{
height: parent.height
width: 32 * screenScaleFactor // Ensure the icon is centered under the extruder icon (same width)
-
+
Rectangle
{
anchors.centerIn: parent
@@ -56,7 +56,7 @@ Item
visible: buildplate
}
}
-
+
Label
{
id: buildplateLabel
@@ -69,6 +69,7 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml
index 0d7a177dd3..08743ed777 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -23,7 +23,7 @@ Item
height: centerSection.height
width: maximumWidth
-
+
// Enable keyboard navigation
Keys.onLeftPressed: navigateTo(currentIndex - 1)
Keys.onRightPressed: navigateTo(currentIndex + 1)
@@ -131,7 +131,7 @@ Item
}
}
spacing: 60 * screenScaleFactor // TODO: Theme!
-
+
Repeater
{
model: printers
@@ -255,4 +255,4 @@ Item
currentIndex = i
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml
index 1718994d83..1fe766d9f7 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -30,6 +30,26 @@ UM.Dialog
OutputDevice.forceSendJob(printer.activePrintJob.key)
overrideConfirmationDialog.close()
}
+ visible:
+ {
+ // Don't show the button if we're missing a printer or print job
+ if (!printer || !printer.activePrintJob)
+ {
+ return false
+ }
+
+ // Check each required change...
+ for (var i = 0; i < printer.activePrintJob.configurationChanges.length; i++)
+ {
+ var change = printer.activePrintJob.configurationChanges[i]
+ // If that type of change is in the list of blocking changes, hide the button
+ if (!change.canOverride)
+ {
+ return false
+ }
+ }
+ return true
+ }
},
Button
{
@@ -52,6 +72,7 @@ UM.Dialog
bottomMargin: 56 * screenScaleFactor // TODO: Theme!
}
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text:
{
if (!printer || !printer.activePrintJob)
@@ -139,4 +160,4 @@ UM.Dialog
}
return translationText
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml
index 771bd4b8cf..34ca3c6df2 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -81,7 +81,7 @@ Item
enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming");
onClicked: {
if (printJob.state == "paused") {
- printJob.setState("print");
+ printJob.setState("resume");
popUp.close();
return;
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml
index ba85802809..aa5d6de89b 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -23,9 +23,10 @@ Button
horizontalAlignment: Text.AlignHCenter
text: base.text
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering;
}
height: width
hoverEnabled: enabled
text: "\u22EE" //Unicode Three stacked points.
width: 36 * screenScaleFactor // TODO: Theme!
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml
index 4079f23b0a..63caaab433 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -56,7 +56,7 @@ Item
Label
{
id: materialLabel
-
+
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("default") // 12pt, regular
@@ -66,6 +66,7 @@ Item
// FIXED-LINE-HEIGHT:
height: parent.height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
@@ -85,7 +86,7 @@ Item
Label
{
id: printCoreLabel
-
+
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("default_bold") // 12pt, bold
@@ -95,6 +96,7 @@ Item
// FIXED-LINE-HEIGHT:
height: parent.height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorIconExtruder.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorIconExtruder.qml
index c3e78317c5..876215d65d 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorIconExtruder.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorIconExtruder.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -48,5 +48,6 @@ Item
x: Math.round(size * 0.25)
y: Math.round(size * 0.15625)
visible: position >= 0
+ renderType: Text.NativeRendering
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorInfoBlurb.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorInfoBlurb.qml
index 21000b8bff..32e19c1cdb 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorInfoBlurb.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorInfoBlurb.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -40,6 +40,7 @@ Item
width: 240 * screenScaleFactor // TODO: Theme!
color: UM.Theme.getColor("monitor_tooltip_text")
font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
}
}
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml
index 41b3a93a7b..1ac72b8f8e 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -42,4 +42,4 @@ Component {
z: 1;
}
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml
index a23b8ab0d3..c01f778bba 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml
@@ -1,6 +1,5 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-
import QtQuick 2.2
import QtQuick.Controls 2.0
import UM 1.3 as UM
@@ -22,10 +21,6 @@ Item
// The print job which all other data is derived from
property var printJob: null
- // If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future
- // they might not need to though.
- property bool cloudConnection: Cura.MachineManager.activeMachineIsUsingCloudConnection
-
width: parent.width
height: childrenRect.height
@@ -51,7 +46,7 @@ Item
{
anchors.verticalCenter: parent.verticalCenter
height: 18 * screenScaleFactor // TODO: Theme!
- width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+ width: UM.Theme.getSize("monitor_column").width
Rectangle
{
color: UM.Theme.getColor("monitor_skeleton_loading")
@@ -69,8 +64,10 @@ Item
visible: printJob
// FIXED-LINE-HEIGHT:
+ width: parent.width
height: parent.height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
@@ -78,7 +75,8 @@ Item
{
anchors.verticalCenter: parent.verticalCenter
height: 18 * screenScaleFactor // TODO: Theme!
- width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+ width: UM.Theme.getSize("monitor_column").width
+
Rectangle
{
color: UM.Theme.getColor("monitor_skeleton_loading")
@@ -87,6 +85,7 @@ Item
visible: !printJob
radius: 2 * screenScaleFactor // TODO: Theme!
}
+
Label
{
text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : ""
@@ -98,6 +97,7 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
@@ -143,6 +143,7 @@ Item
// FIXED-LINE-HEIGHT:
height: parent.height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
Row
@@ -158,14 +159,9 @@ Item
spacing: 6 // TODO: Theme!
visible: printJob
- Repeater
+ MonitorPrinterPill
{
- id: compatiblePills
- delegate: MonitorPrinterPill
- {
- text: modelData
- }
- model: printJob ? printJob.compatibleMachineFamilies : []
+ text: printJob.configuration.printerType
}
}
}
@@ -185,13 +181,10 @@ Item
id: printerConfiguration
anchors.verticalCenter: parent.verticalCenter
buildplate: catalog.i18nc("@label", "Glass")
- configurations:
- [
- base.printJob.configuration.extruderConfigurations[0],
- base.printJob.configuration.extruderConfigurations[1]
- ]
+ configurations: base.printJob.configuration.extruderConfigurations
height: 72 * screenScaleFactor // TODO: Theme!
}
+
Label {
text: printJob && printJob.owner ? printJob.owner : ""
color: UM.Theme.getColor("monitor_text_primary")
@@ -202,6 +195,7 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
}
@@ -218,7 +212,7 @@ Item
}
width: 32 * screenScaleFactor // TODO: Theme!
height: 32 * screenScaleFactor // TODO: Theme!
- enabled: !cloudConnection
+ enabled: OutputDevice.supportsPrintJobActions
onClicked: enabled ? contextMenu.switchPopupState() : {}
visible:
{
@@ -248,10 +242,10 @@ Item
enabled: !contextMenuButton.enabled
}
- MonitorInfoBlurb
- {
- id: contextMenuDisabledInfo
- text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.")
- target: contextMenuButton
- }
-}
\ No newline at end of file
+ MonitorInfoBlurb
+ {
+ id: contextMenuDisabledInfo
+ text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
+ target: contextMenuButton
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml
index a392571757..7492b4e8e4 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -41,7 +41,7 @@ Item
UM.RecolorImage
{
id: ultiBotImage
-
+
anchors.centerIn: printJobPreview
color: UM.Theme.getColor("monitor_placeholder_image")
height: printJobPreview.height
@@ -98,4 +98,4 @@ Item
visible: source != ""
width: 0.5 * printJobPreview.width
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml
index 2ba70268b2..0a478c8543 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -20,49 +20,38 @@ Item
property var printJob: null
width: childrenRect.width
- height: 18 * screenScaleFactor // TODO: Theme!
+ height: UM.Theme.getSize("monitor_text_line").height
- ProgressBar
+ UM.ProgressBar
{
id: progressBar
anchors
{
verticalCenter: parent.verticalCenter
+ left: parent.left
}
value: printJob ? printJob.progress : 0
- style: ProgressBarStyle
- {
- background: Rectangle
- {
- color: UM.Theme.getColor("monitor_progress_bar_empty")
- implicitHeight: visible ? 12 * screenScaleFactor : 0 // TODO: Theme!
- implicitWidth: 180 * screenScaleFactor // TODO: Theme!
- radius: 2 * screenScaleFactor // TODO: Theme!
- }
- progress: Rectangle
- {
- id: progressItem;
- color: printJob && printJob.isActive ? UM.Theme.getColor("monitor_progress_bar_fill") : UM.Theme.getColor("monitor_progress_bar_deactive")
- radius: 2 * screenScaleFactor // TODO: Theme!
- }
- }
+ width: UM.Theme.getSize("monitor_progress_bar").width
}
+
Label
{
id: percentLabel
anchors
{
left: progressBar.right
- leftMargin: 18 * screenScaleFactor // TODO: Theme!
+ leftMargin: UM.Theme.getSize("monitor_margin").width
+ verticalCenter: parent.verticalCenter
}
text: printJob ? Math.round(printJob.progress * 100) + "%" : "0%"
color: printJob && printJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
width: contentWidth
- font: UM.Theme.getFont("medium") // 14pt, regular
+ font: UM.Theme.getFont("default") // 12pt, regular
// FIXED-LINE-HEIGHT:
- height: 18 * screenScaleFactor // TODO: Theme!
+ height: UM.Theme.getSize("monitor_text_line").height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
Label
{
@@ -70,50 +59,52 @@ Item
anchors
{
left: percentLabel.right
- leftMargin: 18 * screenScaleFactor // TODO: Theme!
+ leftMargin: UM.Theme.getSize("monitor_margin").width
+ verticalCenter: parent.verticalCenter
}
color: UM.Theme.getColor("monitor_text_primary")
- font: UM.Theme.getFont("medium") // 14pt, regular
+ font: UM.Theme.getFont("default")
text:
{
if (!printJob)
{
- return ""
+ return "";
}
switch (printJob.state)
{
case "wait_cleanup":
if (printJob.timeTotal > printJob.timeElapsed)
{
- return catalog.i18nc("@label:status", "Aborted")
+ return catalog.i18nc("@label:status", "Aborted");
}
- return catalog.i18nc("@label:status", "Finished")
+ return catalog.i18nc("@label:status", "Finished");
case "finished":
- return catalog.i18nc("@label:status", "Finished")
+ return catalog.i18nc("@label:status", "Finished");
case "sent_to_printer":
- return catalog.i18nc("@label:status", "Preparing...")
+ return catalog.i18nc("@label:status", "Preparing...");
case "pre_print":
- return catalog.i18nc("@label:status", "Preparing...")
+ return catalog.i18nc("@label:status", "Preparing...");
case "aborting": // NOTE: Doesn't exist but maybe should someday
- return catalog.i18nc("@label:status", "Aborting...")
+ return catalog.i18nc("@label:status", "Aborting...");
case "aborted": // NOTE: Unused, see above
- return catalog.i18nc("@label:status", "Aborted")
+ return catalog.i18nc("@label:status", "Aborted");
case "pausing":
- return catalog.i18nc("@label:status", "Pausing...")
+ return catalog.i18nc("@label:status", "Pausing...");
case "paused":
- return catalog.i18nc("@label:status", "Paused")
+ return catalog.i18nc("@label:status", "Paused");
case "resuming":
- return catalog.i18nc("@label:status", "Resuming...")
+ return catalog.i18nc("@label:status", "Resuming...");
case "queued":
- return catalog.i18nc("@label:status", "Action required")
+ return catalog.i18nc("@label:status", "Action required");
default:
- return catalog.i18nc("@label:status", "Finishes %1 at %2".arg(OutputDevice.getDateCompleted( printJob.timeRemaining )).arg(OutputDevice.getTimeCompleted( printJob.timeRemaining )))
+ return catalog.i18nc("@label:status", "Finishes %1 at %2".arg(OutputDevice.getDateCompleted(printJob.timeRemaining)).arg(OutputDevice.getTimeCompleted(printJob.timeRemaining)));
}
}
width: contentWidth
// FIXED-LINE-HEIGHT:
- height: 18 * screenScaleFactor // TODO: Theme!
+ height: UM.Theme.getSize("monitor_text_line").height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
index 8c63e1ef1a..9242abacdd 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
@@ -81,7 +81,7 @@ Item
mipmap: true
}
}
-
+
Item
{
@@ -90,7 +90,7 @@ Item
verticalCenter: parent.verticalCenter
}
width: 180 * screenScaleFactor // TODO: Theme!
- height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
+ height: childrenRect.height
Rectangle
{
@@ -99,7 +99,7 @@ Item
height: 18 * screenScaleFactor // TODO: Theme!
width: parent.width
radius: 2 * screenScaleFactor // TODO: Theme!
-
+
Label
{
text: printer && printer.name ? printer.name : ""
@@ -112,6 +112,7 @@ Item
// FIXED-LINE-HEIGHT:
height: parent.height
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
@@ -134,13 +135,61 @@ Item
}
text: printer ? printer.type : ""
}
+ Item
+ {
+ id: managePrinterLink
+ anchors {
+ top: printerFamilyPill.bottom
+ topMargin: 6 * screenScaleFactor
+ }
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: childrenRect.width
+
+ Label
+ {
+ id: managePrinterText
+ anchors.verticalCenter: managePrinterLink.verticalCenter
+ color: UM.Theme.getColor("monitor_text_link")
+ font: UM.Theme.getFont("default")
+ linkColor: UM.Theme.getColor("monitor_text_link")
+ text: catalog.i18nc("@label link to Connect and Cloud interfaces", "Manage printer")
+ renderType: Text.NativeRendering
+ }
+ UM.RecolorImage
+ {
+ id: externalLinkIcon
+ anchors
+ {
+ left: managePrinterText.right
+ leftMargin: 6 * screenScaleFactor
+ verticalCenter: managePrinterText.verticalCenter
+ }
+ color: UM.Theme.getColor("monitor_text_link")
+ source: UM.Theme.getIcon("external_link")
+ width: 12 * screenScaleFactor
+ height: 12 * screenScaleFactor
+ }
+ }
+ MouseArea
+ {
+ anchors.fill: managePrinterLink
+ onClicked: OutputDevice.openPrintJobControlPanel()
+ onEntered:
+ {
+ manageQueueText.font.underline = true
+ }
+ onExited:
+ {
+ manageQueueText.font.underline = false
+ }
+ }
}
MonitorPrinterConfiguration
{
id: printerConfiguration
anchors.verticalCenter: parent.verticalCenter
- buildplate: printer ? "Glass" : null // 'Glass' as a default
+ buildplate: printer ? catalog.i18nc("@label", "Glass") : null // 'Glass' as a default
configurations:
{
var configs = []
@@ -171,8 +220,7 @@ Item
}
width: 36 * screenScaleFactor // TODO: Theme!
height: 36 * screenScaleFactor // TODO: Theme!
- enabled: !cloudConnection
-
+ enabled: OutputDevice.supportsPrintJobActions
onClicked: enabled ? contextMenu.switchPopupState() : {}
visible:
{
@@ -205,7 +253,7 @@ Item
MonitorInfoBlurb
{
id: contextMenuDisabledInfo
- text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.")
+ text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
target: contextMenuButton
}
@@ -243,7 +291,6 @@ Item
}
}
-
// Divider
Rectangle
{
@@ -315,6 +362,7 @@ Item
return ""
}
visible: text !== ""
+ renderType: Text.NativeRendering
}
Item
@@ -356,6 +404,7 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
Label
@@ -376,6 +425,7 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
@@ -403,6 +453,7 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
}
}
@@ -437,11 +488,31 @@ Item
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
height: 18 * screenScaleFactor // TODO: Theme!
+ renderType: Text.NativeRendering
}
implicitHeight: 32 * screenScaleFactor // TODO: Theme!
implicitWidth: 96 * screenScaleFactor // TODO: Theme!
visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
onClicked: base.enabled ? overrideConfirmationDialog.open() : {}
+ enabled: OutputDevice.supportsPrintJobActions
+ }
+
+ // For cloud printing, add this mouse area over the disabled details button to indicate that it's not available
+ MouseArea
+ {
+ id: detailsButtonDisabledButtonArea
+ anchors.fill: detailsButton
+ hoverEnabled: detailsButton.visible && !detailsButton.enabled
+ onEntered: overrideButtonDisabledInfo.open()
+ onExited: overrideButtonDisabledInfo.close()
+ enabled: !detailsButton.enabled
+ }
+
+ MonitorInfoBlurb
+ {
+ id: overrideButtonDisabledInfo
+ text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
+ target: detailsButton
}
}
@@ -450,4 +521,4 @@ Item
id: overrideConfirmationDialog
printer: base.printer
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml
index dbe085e18e..21d08a310c 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -55,4 +55,4 @@ Item
anchors.bottom: parent.bottom
buildplate: null
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterPill.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterPill.qml
index 2aeecd5a92..44aa1a1f8d 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterPill.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterPill.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -11,20 +11,8 @@ import UM 1.2 as UM
*/
Item
{
- // The printer name
+ id: monitorPrinterPill
property var text: ""
- property var tagText: {
- switch(text) {
- case "Ultimaker 3":
- return "UM 3"
- case "Ultimaker 3 Extended":
- return "UM 3 EXT"
- case "Ultimaker S5":
- return "UM S5"
- default:
- return text
- }
- }
implicitHeight: 18 * screenScaleFactor // TODO: Theme!
implicitWidth: Math.max(printerNameLabel.contentWidth + 12 * screenScaleFactor, 36 * screenScaleFactor) // TODO: Theme!
@@ -40,8 +28,9 @@ Item
id: printerNameLabel
anchors.centerIn: parent
color: UM.Theme.getColor("monitor_text_primary")
- text: tagText
+ text: monitorPrinterPill.text
font.pointSize: 10 // TODO: Theme!
- visible: text !== ""
+ visible: monitorPrinterPill.text !== ""
+ renderType: Text.NativeRendering
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
index ce08f78226..ce692168c3 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -29,6 +29,7 @@ Item
color: UM.Theme.getColor("monitor_text_primary")
font: UM.Theme.getFont("large")
text: catalog.i18nc("@label", "Queued")
+ renderType: Text.NativeRendering
}
Item
@@ -41,7 +42,6 @@ Item
}
height: 18 * screenScaleFactor // TODO: Theme!
width: childrenRect.width
- visible: !cloudConnection
UM.RecolorImage
{
@@ -64,7 +64,7 @@ Item
color: UM.Theme.getColor("monitor_text_link")
font: UM.Theme.getFont("medium") // 14pt, regular
linkColor: UM.Theme.getColor("monitor_text_link")
- text: catalog.i18nc("@label link to connect manager", "Go to Cura Connect")
+ text: catalog.i18nc("@label link to connect manager", "Manage in browser")
renderType: Text.NativeRendering
}
}
@@ -72,9 +72,7 @@ Item
MouseArea
{
anchors.fill: manageQueueLabel
- enabled: !cloudConnection
- hoverEnabled: !cloudConnection
- onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
+ onClicked: OutputDevice.openPrintJobControlPanel()
onEntered:
{
manageQueueText.font.underline = true
@@ -97,6 +95,21 @@ Item
}
spacing: 18 * screenScaleFactor // TODO: Theme!
+ Label
+ {
+ text: catalog.i18nc("@label", "There are no print jobs in the queue. Slice and send a job to add one.")
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ anchors.verticalCenter: parent.verticalCenter
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ visible: printJobList.count === 0
+ }
+
Label
{
text: catalog.i18nc("@label", "Print jobs")
@@ -109,6 +122,8 @@ Item
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ visible: printJobList.count > 0
}
Label
@@ -118,11 +133,13 @@ Item
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
anchors.verticalCenter: parent.verticalCenter
- width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+ width: UM.Theme.getSize("monitor_column").width
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ visible: printJobList.count > 0
}
Label
@@ -132,11 +149,13 @@ Item
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
anchors.verticalCenter: parent.verticalCenter
- width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+ width: UM.Theme.getSize("monitor_column").width
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ visible: printJobList.count > 0
}
}
@@ -168,10 +187,7 @@ Item
}
model:
{
- // When printing over the cloud we don't recieve print jobs until there is one, so
- // unless there's at least one print job we'll be stuck with skeleton loading
- // indefinitely.
- if (Cura.MachineManager.activeMachineIsUsingCloudConnection || OutputDevice.receivedPrintJobs)
+ if (OutputDevice.receivedData)
{
return OutputDevice.queuedPrintJobs
}
@@ -180,88 +196,4 @@ Item
spacing: 6 // TODO: Theme!
}
}
-
- Rectangle
- {
- anchors
- {
- horizontalCenter: parent.horizontalCenter
- top: printJobQueueHeadings.bottom
- topMargin: 12 * screenScaleFactor // TODO: Theme!
- }
- height: 48 * screenScaleFactor // TODO: Theme!
- width: parent.width
- color: UM.Theme.getColor("monitor_card_background")
- border.color: UM.Theme.getColor("monitor_card_border")
- radius: 2 * screenScaleFactor // TODO: Theme!
-
- visible: printJobList.model.length == 0
-
- Row
- {
- anchors
- {
- left: parent.left
- leftMargin: 18 * screenScaleFactor // TODO: Theme!
- verticalCenter: parent.verticalCenter
- }
- spacing: 18 * screenScaleFactor // TODO: Theme!
- height: 18 * screenScaleFactor // TODO: Theme!
-
- Label
- {
- text: "All jobs are printed."
- color: UM.Theme.getColor("monitor_text_primary")
- font: UM.Theme.getFont("medium") // 14pt, regular
- }
-
- Item
- {
- id: viewPrintHistoryLabel
-
- height: 18 * screenScaleFactor // TODO: Theme!
- width: childrenRect.width
- visible: !cloudConnection
-
- UM.RecolorImage
- {
- id: printHistoryIcon
- anchors.verticalCenter: parent.verticalCenter
- color: UM.Theme.getColor("monitor_text_link")
- source: UM.Theme.getIcon("external_link")
- width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
- height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
- }
- Label
- {
- id: viewPrintHistoryText
- anchors
- {
- left: printHistoryIcon.right
- leftMargin: 6 * screenScaleFactor // TODO: Theme!
- verticalCenter: printHistoryIcon.verticalCenter
- }
- color: UM.Theme.getColor("monitor_text_link")
- font: UM.Theme.getFont("medium") // 14pt, regular
- linkColor: UM.Theme.getColor("monitor_text_link")
- text: catalog.i18nc("@label link to connect manager", "View print history")
- renderType: Text.NativeRendering
- }
- MouseArea
- {
- anchors.fill: parent
- hoverEnabled: true
- onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
- onEntered:
- {
- viewPrintHistoryText.font.underline = true
- }
- onExited:
- {
- viewPrintHistoryText.font.underline = false
- }
- }
- }
- }
- }
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml
index 59cbda7172..47c45f8b11 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -25,7 +25,7 @@ Component
}
width: maximumWidth
color: UM.Theme.getColor("monitor_stage_background")
-
+
// Enable keyboard navigation. NOTE: This is done here so that we can also potentially
// forward to the queue items in the future. (Deleting selected print job, etc.)
Keys.forwardTo: carousel
@@ -50,7 +50,14 @@ Component
MonitorCarousel
{
id: carousel
- printers: OutputDevice.receivedPrintJobs ? OutputDevice.printers : [null]
+ printers:
+ {
+ if (OutputDevice.receivedData)
+ {
+ return OutputDevice.printers
+ }
+ return [null]
+ }
}
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml
index 67c82db320..78b94ce259 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
@@ -16,8 +16,9 @@ Button {
text: parent.text
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
+ renderType: Text.NativeRendering;
}
height: visible ? 39 * screenScaleFactor : 0; // TODO: Theme!
hoverEnabled: true;
width: parent.width;
-}
\ No newline at end of file
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml
index c2590e99a8..6d9f375788 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml
@@ -1,52 +1,57 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-
import QtQuick 2.2
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
import UM 1.1 as UM
UM.Dialog {
+
id: base;
+ title: catalog.i18nc("@title:window", "Print over network");
+ width: minimumWidth;
height: minimumHeight;
- leftButtons: [
- Button {
- enabled: true;
- onClicked: {
- base.visible = false;
- printerSelectionCombobox.currentIndex = 0;
- OutputDevice.cancelPrintSelection();
- }
- text: catalog.i18nc("@action:button","Cancel");
- }
- ]
maximumHeight: minimumHeight;
maximumWidth: minimumWidth;
minimumHeight: 140 * screenScaleFactor;
minimumWidth: 500 * screenScaleFactor;
modality: Qt.ApplicationModal;
- onVisibleChanged: {
- if (visible) {
- resetPrintersModel();
- } else {
- OutputDevice.cancelPrintSelection();
+
+ Component.onCompleted: {
+ populateComboBox()
+ }
+
+ // populates the combo box with the correct printer values
+ function populateComboBox() {
+ comboBoxPrintersModel.clear();
+ comboBoxPrintersModel.append({ name: "Automatic", key: "" }); // Connect will just do it's thing
+ for (var i in OutputDevice.printers) {
+ comboBoxPrintersModel.append({
+ name: OutputDevice.printers[i].name,
+ key: OutputDevice.printers[i].uniqueName
+ });
}
}
+
+ leftButtons: [
+ Button {
+ enabled: true;
+ onClicked: {
+ base.close();
+ }
+ text: catalog.i18nc("@action:button","Cancel");
+ }
+ ]
rightButtons: [
Button {
enabled: true;
onClicked: {
- base.visible = false;
- OutputDevice.selectPrinter(printerSelectionCombobox.model.get(printerSelectionCombobox.currentIndex).key);
- // reset to defaults
- printerSelectionCombobox.currentIndex = 0;
+ OutputDevice.selectTargetPrinter(printerComboBox.model.get(printerComboBox.currentIndex).key);
+ base.close();
}
text: catalog.i18nc("@action:button","Print");
}
]
- title: catalog.i18nc("@title:window", "Print over network");
- visible: true;
- width: minimumWidth;
Column {
id: printerSelection;
@@ -59,10 +64,6 @@ UM.Dialog {
}
height: 50 * screenScaleFactor;
- SystemPalette {
- id: palette;
- }
-
UM.I18nCatalog {
id: catalog;
name: "cura";
@@ -78,26 +79,18 @@ UM.Dialog {
height: 20 * screenScaleFactor;
text: catalog.i18nc("@label", "Printer selection");
wrapMode: Text.Wrap;
+ renderType: Text.NativeRendering;
}
ComboBox {
- id: printerSelectionCombobox;
+ id: printerComboBox;
Behavior on height { NumberAnimation { duration: 100 } }
height: 40 * screenScaleFactor;
model: ListModel {
- id: printersModel;
+ id: comboBoxPrintersModel;
}
textRole: "name";
width: parent.width;
}
}
-
- // Utils
- function resetPrintersModel() {
- printersModel.clear();
- printersModel.append({ name: "Automatic", key: ""});
- for (var index in OutputDevice.printers) {
- printersModel.append({name: OutputDevice.printers[index].name, key: OutputDevice.printers[index].key});
- }
- }
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml
index 77b481f6d8..cfbb30fdfb 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
diff --git a/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml b/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml
deleted file mode 100644
index c99ed1688e..0000000000
--- a/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2018 Ultimaker B.V.
-// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
-import UM 1.2 as UM
-import Cura 1.0 as Cura
-
-Item {
- id: base;
- property string activeQualityDefinitionId: Cura.MachineManager.activeQualityDefinitionId;
- property bool isUM3: activeQualityDefinitionId == "ultimaker3" || activeQualityDefinitionId.match("ultimaker_") != null;
- property bool printerConnected: Cura.MachineManager.printerConnected;
- property bool printerAcceptsCommands:
- {
- if (printerConnected && Cura.MachineManager.printerOutputDevices[0])
- {
- return Cura.MachineManager.printerOutputDevices[0].acceptsCommands
- }
- return false
- }
- property bool authenticationRequested:
- {
- if (printerConnected && Cura.MachineManager.printerOutputDevices[0])
- {
- var device = Cura.MachineManager.printerOutputDevices[0]
- // AuthState.AuthenticationRequested or AuthState.AuthenticationReceived
- return device.authenticationState == 2 || device.authenticationState == 5
- }
- return false
- }
- property var materialNames:
- {
- if (printerConnected && Cura.MachineManager.printerOutputDevices[0])
- {
- return Cura.MachineManager.printerOutputDevices[0].materialNames
- }
- return null
- }
- property var hotendIds:
- {
- if (printerConnected && Cura.MachineManager.printerOutputDevices[0])
- {
- return Cura.MachineManager.printerOutputDevices[0].hotendIds
- }
- return null
- }
-
- UM.I18nCatalog {
- id: catalog;
- name: "cura";
- }
-
- Row {
- objectName: "networkPrinterConnectButton";
- spacing: UM.Theme.getSize("default_margin").width;
- visible: isUM3;
-
- Button {
- height: UM.Theme.getSize("save_button_save_to_button").height;
- onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication();
- style: UM.Theme.styles.print_setup_action_button;
- text: catalog.i18nc("@action:button", "Request Access");
- tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer");
- visible: printerConnected && !printerAcceptsCommands && !authenticationRequested;
- }
-
- Button {
- height: UM.Theme.getSize("save_button_save_to_button").height;
- onClicked: connectActionDialog.show();
- style: UM.Theme.styles.print_setup_action_button;
- text: catalog.i18nc("@action:button", "Connect");
- tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer");
- visible: !printerConnected;
- }
- }
-
- UM.Dialog {
- id: connectActionDialog;
- rightButtons: Button {
- iconName: "dialog-close";
- onClicked: connectActionDialog.reject();
- text: catalog.i18nc("@action:button", "Close");
- }
-
- Loader {
- anchors.fill: parent;
- source: "DiscoverUM3Action.qml";
- }
- }
-}
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
index adff94bbbc..ed8d22a478 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import json
from json import JSONDecodeError
@@ -11,18 +11,19 @@ from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManage
from UM.Logger import Logger
from cura import UltimakerCloudAuthentication
from cura.API import Account
+
from .ToolPathUploader import ToolPathUploader
-from ..Models import BaseModel
-from .Models.CloudClusterResponse import CloudClusterResponse
-from .Models.CloudError import CloudError
-from .Models.CloudClusterStatus import CloudClusterStatus
-from .Models.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
-from .Models.CloudPrintResponse import CloudPrintResponse
-from .Models.CloudPrintJobResponse import CloudPrintJobResponse
+from ..Models.BaseModel import BaseModel
+from ..Models.Http.CloudClusterResponse import CloudClusterResponse
+from ..Models.Http.CloudError import CloudError
+from ..Models.Http.CloudClusterStatus import CloudClusterStatus
+from ..Models.Http.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
+from ..Models.Http.CloudPrintResponse import CloudPrintResponse
+from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse
## The generic type variable used to document the methods below.
-CloudApiClientModel = TypeVar("CloudApiClientModel", bound = BaseModel)
+CloudApiClientModel = TypeVar("CloudApiClientModel", bound=BaseModel)
## The cloud API client is responsible for handling the requests and responses from the cloud.
@@ -34,6 +35,9 @@ class CloudApiClient:
CLUSTER_API_ROOT = "{}/connect/v1".format(ROOT_PATH)
CURA_API_ROOT = "{}/cura/v1".format(ROOT_PATH)
+ # In order to avoid garbage collection we keep the callbacks in this list.
+ _anti_gc_callbacks = [] # type: List[Callable[[], None]]
+
## Initializes a new cloud API client.
# \param account: The user's account object
# \param on_error: The callback to be called whenever we receive errors from the server.
@@ -43,8 +47,6 @@ class CloudApiClient:
self._account = account
self._on_error = on_error
self._upload = None # type: Optional[ToolPathUploader]
- # In order to avoid garbage collection we keep the callbacks in this list.
- self._anti_gc_callbacks = [] # type: List[Callable[[], None]]
## Gets the account used for the API.
@property
@@ -54,7 +56,7 @@ class CloudApiClient:
## Retrieves all the clusters for the user that is currently logged in.
# \param on_finished: The function to be called after the result is parsed.
def getClusters(self, on_finished: Callable[[List[CloudClusterResponse]], Any]) -> None:
- url = "{}/clusters".format(self.CLUSTER_API_ROOT)
+ url = "{}/clusters?status=active".format(self.CLUSTER_API_ROOT)
reply = self._manager.get(self._createEmptyRequest(url))
self._addCallback(reply, on_finished, CloudClusterResponse)
@@ -69,8 +71,8 @@ class CloudApiClient:
## Requests the cloud to register the upload of a print job mesh.
# \param request: The request object.
# \param on_finished: The function to be called after the result is parsed.
- def requestUpload(self, request: CloudPrintJobUploadRequest, on_finished: Callable[[CloudPrintJobResponse], Any]
- ) -> None:
+ def requestUpload(self, request: CloudPrintJobUploadRequest,
+ on_finished: Callable[[CloudPrintJobResponse], Any]) -> None:
url = "{}/jobs/upload".format(self.CURA_API_ROOT)
body = json.dumps({"data": request.toDict()})
reply = self._manager.put(self._createEmptyRequest(url), body.encode())
@@ -96,6 +98,16 @@ class CloudApiClient:
reply = self._manager.post(self._createEmptyRequest(url), b"")
self._addCallback(reply, on_finished, CloudPrintResponse)
+ ## Send a print job action to the cluster for the given print job.
+ # \param cluster_id: The ID of the cluster.
+ # \param cluster_job_id: The ID of the print job within the cluster.
+ # \param action: The name of the action to execute.
+ def doPrintJobAction(self, cluster_id: str, cluster_job_id: str, action: str,
+ data: Optional[Dict[str, Any]] = None) -> None:
+ body = json.dumps({"data": data}).encode() if data else b""
+ url = "{}/clusters/{}/print_jobs/{}/action/{}".format(self.CLUSTER_API_ROOT, cluster_id, cluster_job_id, action)
+ self._manager.post(self._createEmptyRequest(url), body)
+
## We override _createEmptyRequest in order to add the user credentials.
# \param url: The URL to request
# \param content_type: The type of the body contents.
@@ -156,12 +168,16 @@ class CloudApiClient:
reply: QNetworkReply,
on_finished: Union[Callable[[CloudApiClientModel], Any],
Callable[[List[CloudApiClientModel]], Any]],
- model: Type[CloudApiClientModel],
- ) -> None:
+ model: Type[CloudApiClientModel]) -> None:
def parse() -> None:
- status_code, response = self._parseReply(reply)
self._anti_gc_callbacks.remove(parse)
- return self._parseModels(response, on_finished, model)
+
+ # Don't try to parse the reply if we didn't get one
+ if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None:
+ return
+
+ status_code, response = self._parseReply(reply)
+ self._parseModels(response, on_finished, model)
self._anti_gc_callbacks.append(parse)
reply.finished.connect(parse)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py
deleted file mode 100644
index bd56ef3185..0000000000
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
-
-from typing import TYPE_CHECKING
-if TYPE_CHECKING:
- from .CloudOutputDevice import CloudOutputDevice
-
-
-class CloudOutputController(PrinterOutputController):
- def __init__(self, output_device: "CloudOutputDevice") -> None:
- super().__init__(output_device)
-
- # The cloud connection only supports fetching the printer and queue status and adding a job to the queue.
- # To let the UI know this we mark all features below as False.
- self.can_pause = False
- self.can_abort = False
- self.can_pre_heat_bed = False
- self.can_pre_heat_hotends = False
- self.can_send_raw_gcode = False
- self.can_control_manually = False
- self.can_update_firmware = False
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
index d052d925d2..b544490cfb 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
@@ -1,39 +1,34 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import os
-
from time import time
-from typing import Dict, List, Optional, Set, cast
+from typing import List, Optional, cast
from PyQt5.QtCore import QObject, QUrl, pyqtProperty, pyqtSignal, pyqtSlot
+from PyQt5.QtGui import QDesktopServices
from UM import i18nCatalog
from UM.Backend.Backend import BackendState
from UM.FileHandler.FileHandler import FileHandler
from UM.Logger import Logger
-from UM.Message import Message
-from UM.PluginRegistry import PluginRegistry
-from UM.Qt.Duration import Duration, DurationFormat
from UM.Scene.SceneNode import SceneNode
-
+from UM.Version import Version
from cura.CuraApplication import CuraApplication
-from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
-from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-from cura.PrinterOutputDevice import ConnectionType
+from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
-from .CloudOutputController import CloudOutputController
-from ..MeshFormatHandler import MeshFormatHandler
-from ..UM3PrintJobOutputModel import UM3PrintJobOutputModel
-from .CloudProgressMessage import CloudProgressMessage
from .CloudApiClient import CloudApiClient
-from .Models.CloudClusterResponse import CloudClusterResponse
-from .Models.CloudClusterStatus import CloudClusterStatus
-from .Models.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
-from .Models.CloudPrintResponse import CloudPrintResponse
-from .Models.CloudPrintJobResponse import CloudPrintJobResponse
-from .Models.CloudClusterPrinterStatus import CloudClusterPrinterStatus
-from .Models.CloudClusterPrintJobStatus import CloudClusterPrintJobStatus
-from .Utils import findChanges, formatDateCompleted, formatTimeCompleted
+from ..ExportFileJob import ExportFileJob
+from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
+from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage
+from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage
+from ..Messages.PrintJobUploadSuccessMessage import PrintJobUploadSuccessMessage
+from ..Models.Http.CloudClusterResponse import CloudClusterResponse
+from ..Models.Http.CloudClusterStatus import CloudClusterStatus
+from ..Models.Http.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
+from ..Models.Http.CloudPrintResponse import CloudPrintResponse
+from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse
+from ..Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
+from ..Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
I18N_CATALOG = i18nCatalog("cura")
@@ -43,20 +38,22 @@ I18N_CATALOG = i18nCatalog("cura")
# Currently it only supports viewing the printer and print job status and adding a new job to the queue.
# As such, those methods have been implemented here.
# Note that this device represents a single remote cluster, not a list of multiple clusters.
-class CloudOutputDevice(NetworkedPrinterOutputDevice):
+class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
- # The interval with which the remote clusters are checked
+ # The interval with which the remote cluster is checked.
+ # We can do this relatively often as this API call is quite fast.
CHECK_CLUSTER_INTERVAL = 10.0 # seconds
- # Signal triggered when the print jobs in the queue were changed.
- printJobsChanged = pyqtSignal()
+ # Override the network response timeout in seconds after which we consider the device offline.
+ # For cloud this needs to be higher because the interval at which we check the status is higher as well.
+ NETWORK_RESPONSE_CONSIDER_OFFLINE = 15.0 # seconds
- # Signal triggered when the selected printer in the UI should be changed.
- activePrinterChanged = pyqtSignal()
+ # The minimum version of firmware that support print job actions over cloud.
+ PRINT_JOB_ACTIONS_MIN_VERSION = Version("5.3.0")
# Notify can only use signals that are defined by the class that they are in, not inherited ones.
# Therefore we create a private signal used to trigger the printersChanged signal.
- _clusterPrintersChanged = pyqtSignal()
+ _cloudClusterPrintersChanged = pyqtSignal()
## Creates a new cloud output device
# \param api_client: The client that will run the API calls
@@ -68,49 +65,36 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
# Because the cloud connection does not off all of these, we manually construct this version here.
# An example of why this is needed is the selection of the compatible file type when exporting the tool path.
properties = {
- b"address": b"",
- b"name": cluster.host_name.encode() if cluster.host_name else b"",
+ b"address": cluster.host_internal_ip.encode() if cluster.host_internal_ip else b"",
+ b"name": cluster.friendly_name.encode() if cluster.friendly_name else b"",
b"firmware_version": cluster.host_version.encode() if cluster.host_version else b"",
- b"printer_type": b""
+ b"printer_type": cluster.printer_type.encode() if cluster.printer_type else b"",
+ b"cluster_size": b"1" # cloud devices are always clusters of at least one
}
- super().__init__(device_id = cluster.cluster_id, address = "",
- connection_type = ConnectionType.CloudConnection, properties = properties, parent = parent)
- self._api = api_client
- self._cluster = cluster
+ super().__init__(
+ device_id=cluster.cluster_id,
+ address="",
+ connection_type=ConnectionType.CloudConnection,
+ properties=properties,
+ parent=parent
+ )
+ self._api = api_client
+ self._account = api_client.account
+ self._cluster = cluster
+ self.setAuthenticationState(AuthState.NotAuthenticated)
self._setInterfaceElements()
- self._account = api_client.account
-
- # We use the Cura Connect monitor tab to get most functionality right away.
- if PluginRegistry.getInstance() is not None:
- self._monitor_view_qml_path = os.path.join(
- PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
- "resources", "qml", "MonitorStage.qml"
- )
-
# Trigger the printersChanged signal when the private signal is triggered.
- self.printersChanged.connect(self._clusterPrintersChanged)
-
- # We keep track of which printer is visible in the monitor page.
- self._active_printer = None # type: Optional[PrinterOutputModel]
-
- # Properties to populate later on with received cloud data.
- self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
- self._number_of_extruders = 2 # All networked printers are dual-extrusion Ultimaker machines.
-
- # We only allow a single upload at a time.
- self._progress = CloudProgressMessage()
+ self.printersChanged.connect(self._cloudClusterPrintersChanged)
# Keep server string of the last generated time to avoid updating models more than once for the same response
- self._received_printers = None # type: Optional[List[CloudClusterPrinterStatus]]
- self._received_print_jobs = None # type: Optional[List[CloudClusterPrintJobStatus]]
-
- # A set of the user's job IDs that have finished
- self._finished_jobs = set() # type: Set[str]
+ self._received_printers = None # type: Optional[List[ClusterPrinterStatus]]
+ self._received_print_jobs = None # type: Optional[List[ClusterPrintJobStatus]]
# Reference to the uploaded print job / mesh
+ # We do this to prevent re-uploading the same file multiple times.
self._tool_path = None # type: Optional[bytes]
self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse]
@@ -121,9 +105,12 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
super().connect()
Logger.log("i", "Connected to cluster %s", self.key)
CuraApplication.getInstance().getBackend().backendStateChange.connect(self._onBackendStateChange)
+ self._update()
## Disconnects the device
def disconnect(self) -> None:
+ if not self.isConnected():
+ return
super().disconnect()
Logger.log("i", "Disconnected from cluster %s", self.key)
CuraApplication.getInstance().getBackend().backendStateChange.disconnect(self._onBackendStateChange)
@@ -133,6 +120,149 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
self._tool_path = None
self._uploaded_print_job = None
+ ## Checks whether the given network key is found in the cloud's host name
+ def matchesNetworkKey(self, network_key: str) -> bool:
+ # Typically, a network key looks like "ultimakersystem-aabbccdd0011._ultimaker._tcp.local."
+ # the host name should then be "ultimakersystem-aabbccdd0011"
+ if network_key.startswith(str(self.clusterData.host_name or "")):
+ return True
+ # However, for manually added printers, the local IP address is used in lieu of a proper
+ # network key, so check for that as well. It is in the format "manual:10.1.10.1".
+ if network_key.endswith(str(self.clusterData.host_internal_ip or "")):
+ return True
+ return False
+
+ ## Set all the interface elements and texts for this output device.
+ def _setInterfaceElements(self) -> None:
+ self.setPriority(2) # Make sure we end up below the local networking and above 'save to file'.
+ self.setShortDescription(I18N_CATALOG.i18nc("@action:button", "Print via Cloud"))
+ self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print via Cloud"))
+ self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
+
+ ## Called when the network data should be updated.
+ def _update(self) -> None:
+ super()._update()
+ if time() - self._time_of_last_request < self.CHECK_CLUSTER_INTERVAL:
+ return # avoid calling the cloud too often
+ self._time_of_last_request = time()
+ if self._account.isLoggedIn:
+ self.setAuthenticationState(AuthState.Authenticated)
+ self._last_request_time = time()
+ self._api.getClusterStatus(self.key, self._onStatusCallFinished)
+ else:
+ self.setAuthenticationState(AuthState.NotAuthenticated)
+
+ ## Method called when HTTP request to status endpoint is finished.
+ # Contains both printers and print jobs statuses in a single response.
+ def _onStatusCallFinished(self, status: CloudClusterStatus) -> None:
+ self._responseReceived()
+ if status.printers != self._received_printers:
+ self._received_printers = status.printers
+ self._updatePrinters(status.printers)
+ if status.print_jobs != self._received_print_jobs:
+ self._received_print_jobs = status.print_jobs
+ self._updatePrintJobs(status.print_jobs)
+
+ ## Called when Cura requests an output device to receive a (G-code) file.
+ def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
+ file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
+
+ # Show an error message if we're already sending a job.
+ if self._progress.visible:
+ PrintJobUploadBlockedMessage().show()
+ return
+
+ # Indicate we have started sending a job.
+ self.writeStarted.emit(self)
+
+ # The mesh didn't change, let's not upload it to the cloud again.
+ # Note that self.writeFinished is called in _onPrintUploadCompleted as well.
+ if self._uploaded_print_job:
+ self._api.requestPrint(self.key, self._uploaded_print_job.job_id, self._onPrintUploadCompleted)
+ return
+
+ # Export the scene to the correct file type.
+ job = ExportFileJob(file_handler=file_handler, nodes=nodes, firmware_version=self.firmwareVersion)
+ job.finished.connect(self._onPrintJobCreated)
+ job.start()
+
+ ## Handler for when the print job was created locally.
+ # It can now be sent over the cloud.
+ def _onPrintJobCreated(self, job: ExportFileJob) -> None:
+ output = job.getOutput()
+ self._tool_path = output # store the tool path to prevent re-uploading when printing the same file again
+ request = CloudPrintJobUploadRequest(
+ job_name=job.getFileName(),
+ file_size=len(output),
+ content_type=job.getMimeType(),
+ )
+ self._api.requestUpload(request, self._uploadPrintJob)
+
+ ## Uploads the mesh when the print job was registered with the cloud API.
+ # \param job_response: The response received from the cloud API.
+ def _uploadPrintJob(self, job_response: CloudPrintJobResponse) -> None:
+ if not self._tool_path:
+ return self._onUploadError()
+ self._progress.show()
+ self._uploaded_print_job = job_response # store the last uploaded job to prevent re-upload of the same file
+ self._api.uploadToolPath(job_response, self._tool_path, self._onPrintJobUploaded, self._progress.update,
+ self._onUploadError)
+
+ ## Requests the print to be sent to the printer when we finished uploading the mesh.
+ def _onPrintJobUploaded(self) -> None:
+ self._progress.update(100)
+ print_job = cast(CloudPrintJobResponse, self._uploaded_print_job)
+ self._api.requestPrint(self.key, print_job.job_id, self._onPrintUploadCompleted)
+
+ ## Shows a message when the upload has succeeded
+ # \param response: The response from the cloud API.
+ def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None:
+ self._progress.hide()
+ PrintJobUploadSuccessMessage().show()
+ self.writeFinished.emit()
+
+ ## Displays the given message if uploading the mesh has failed
+ # \param message: The message to display.
+ def _onUploadError(self, message: str = None) -> None:
+ self._progress.hide()
+ self._uploaded_print_job = None
+ PrintJobUploadErrorMessage(message).show()
+ self.writeError.emit()
+
+ ## Whether the printer that this output device represents supports print job actions via the cloud.
+ @pyqtProperty(bool, notify=_cloudClusterPrintersChanged)
+ def supportsPrintJobActions(self) -> bool:
+ if not self._printers:
+ return False
+ version_number = self.printers[0].firmwareVersion.split(".")
+ firmware_version = Version([version_number[0], version_number[1], version_number[2]])
+ return firmware_version >= self.PRINT_JOB_ACTIONS_MIN_VERSION
+
+ ## Set the remote print job state.
+ def setJobState(self, print_job_uuid: str, state: str) -> None:
+ self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, state)
+
+ @pyqtSlot(str, name="sendJobToTop")
+ def sendJobToTop(self, print_job_uuid: str) -> None:
+ self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "move",
+ {"list": "queued", "to_position": 0})
+
+ @pyqtSlot(str, name="deleteJobFromQueue")
+ def deleteJobFromQueue(self, print_job_uuid: str) -> None:
+ self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "remove")
+
+ @pyqtSlot(str, name="forceSendJob")
+ def forceSendJob(self, print_job_uuid: str) -> None:
+ self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "force")
+
+ @pyqtSlot(name="openPrintJobControlPanel")
+ def openPrintJobControlPanel(self) -> None:
+ QDesktopServices.openUrl(QUrl(self.clusterCloudUrl))
+
+ @pyqtSlot(name="openPrinterControlPanel")
+ def openPrinterControlPanel(self) -> None:
+ QDesktopServices.openUrl(QUrl(self.clusterCloudUrl))
+
## Gets the cluster response from which this device was created.
@property
def clusterData(self) -> CloudClusterResponse:
@@ -143,298 +273,8 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
def clusterData(self, value: CloudClusterResponse) -> None:
self._cluster = value
- ## Checks whether the given network key is found in the cloud's host name
- def matchesNetworkKey(self, network_key: str) -> bool:
- # A network key looks like "ultimakersystem-aabbccdd0011._ultimaker._tcp.local."
- # the host name should then be "ultimakersystem-aabbccdd0011"
- return network_key.startswith(self.clusterData.host_name)
-
- ## Set all the interface elements and texts for this output device.
- def _setInterfaceElements(self) -> None:
- self.setPriority(2) # Make sure we end up below the local networking and above 'save to file'
- self.setName(self._id)
- self.setShortDescription(I18N_CATALOG.i18nc("@action:button", "Print via Cloud"))
- self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print via Cloud"))
- self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
-
- ## Called when Cura requests an output device to receive a (G-code) file.
- def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
- file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
-
- # Show an error message if we're already sending a job.
- if self._progress.visible:
- message = Message(
- text = I18N_CATALOG.i18nc("@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job."),
- title = I18N_CATALOG.i18nc("@info:title", "Cloud error"),
- lifetime = 10
- )
- message.show()
- return
-
- if self._uploaded_print_job:
- # The mesh didn't change, let's not upload it again
- self._api.requestPrint(self.key, self._uploaded_print_job.job_id, self._onPrintUploadCompleted)
- return
-
- # Indicate we have started sending a job.
- self.writeStarted.emit(self)
-
- mesh_format = MeshFormatHandler(file_handler, self.firmwareVersion)
- if not mesh_format.is_valid:
- Logger.log("e", "Missing file or mesh writer!")
- return self._onUploadError(I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
-
- mesh = mesh_format.getBytes(nodes)
-
- self._tool_path = mesh
- request = CloudPrintJobUploadRequest(
- job_name = file_name or mesh_format.file_extension,
- file_size = len(mesh),
- content_type = mesh_format.mime_type,
- )
- self._api.requestUpload(request, self._onPrintJobCreated)
-
- ## Called when the network data should be updated.
- def _update(self) -> None:
- super()._update()
- if self._last_request_time and time() - self._last_request_time < self.CHECK_CLUSTER_INTERVAL:
- return # Avoid calling the cloud too often
-
- Logger.log("d", "Updating: %s - %s >= %s", time(), self._last_request_time, self.CHECK_CLUSTER_INTERVAL)
- if self._account.isLoggedIn:
- self.setAuthenticationState(AuthState.Authenticated)
- self._last_request_time = time()
- self._api.getClusterStatus(self.key, self._onStatusCallFinished)
- else:
- self.setAuthenticationState(AuthState.NotAuthenticated)
-
- ## Method called when HTTP request to status endpoint is finished.
- # Contains both printers and print jobs statuses in a single response.
- def _onStatusCallFinished(self, status: CloudClusterStatus) -> None:
- # Update all data from the cluster.
- self._last_response_time = time()
- if self._received_printers != status.printers:
- self._received_printers = status.printers
- self._updatePrinters(status.printers)
-
- if status.print_jobs != self._received_print_jobs:
- self._received_print_jobs = status.print_jobs
- self._updatePrintJobs(status.print_jobs)
-
- ## Updates the local list of printers with the list received from the cloud.
- # \param jobs: The printers received from the cloud.
- def _updatePrinters(self, printers: List[CloudClusterPrinterStatus]) -> None:
- previous = {p.key: p for p in self._printers} # type: Dict[str, PrinterOutputModel]
- received = {p.uuid: p for p in printers} # type: Dict[str, CloudClusterPrinterStatus]
-
- removed_printers, added_printers, updated_printers = findChanges(previous, received)
-
- for removed_printer in removed_printers:
- if self._active_printer == removed_printer:
- self.setActivePrinter(None)
- self._printers.remove(removed_printer)
-
- for added_printer in added_printers:
- self._printers.append(added_printer.createOutputModel(CloudOutputController(self)))
-
- for model, printer in updated_printers:
- printer.updateOutputModel(model)
-
- # Always have an active printer
- if self._printers and not self._active_printer:
- self.setActivePrinter(self._printers[0])
-
- if added_printers or removed_printers:
- self.printersChanged.emit()
-
- ## Updates the local list of print jobs with the list received from the cloud.
- # \param jobs: The print jobs received from the cloud.
- def _updatePrintJobs(self, jobs: List[CloudClusterPrintJobStatus]) -> None:
- received = {j.uuid: j for j in jobs} # type: Dict[str, CloudClusterPrintJobStatus]
- previous = {j.key: j for j in self._print_jobs} # type: Dict[str, UM3PrintJobOutputModel]
-
- removed_jobs, added_jobs, updated_jobs = findChanges(previous, received)
-
- for removed_job in removed_jobs:
- if removed_job.assignedPrinter:
- removed_job.assignedPrinter.updateActivePrintJob(None)
- removed_job.stateChanged.disconnect(self._onPrintJobStateChanged)
- self._print_jobs.remove(removed_job)
-
- for added_job in added_jobs:
- self._addPrintJob(added_job)
-
- for model, job in updated_jobs:
- job.updateOutputModel(model)
- if job.printer_uuid:
- self._updateAssignedPrinter(model, job.printer_uuid)
-
- # We only have to update when jobs are added or removed
- # updated jobs push their changes via their output model
- if added_jobs or removed_jobs:
- self.printJobsChanged.emit()
-
- ## Registers a new print job received via the cloud API.
- # \param job: The print job received.
- def _addPrintJob(self, job: CloudClusterPrintJobStatus) -> None:
- model = job.createOutputModel(CloudOutputController(self))
- model.stateChanged.connect(self._onPrintJobStateChanged)
- if job.printer_uuid:
- self._updateAssignedPrinter(model, job.printer_uuid)
- self._print_jobs.append(model)
-
- ## Handles the event of a change in a print job state
- def _onPrintJobStateChanged(self) -> None:
- user_name = self._getUserName()
- # TODO: confirm that notifications in Cura are still required
- for job in self._print_jobs:
- if job.state == "wait_cleanup" and job.key not in self._finished_jobs and job.owner == user_name:
- self._finished_jobs.add(job.key)
- Message(
- title = I18N_CATALOG.i18nc("@info:status", "Print finished"),
- text = (I18N_CATALOG.i18nc("@info:status", "Printer '{printer_name}' has finished printing '{job_name}'.").format(
- printer_name = job.assignedPrinter.name,
- job_name = job.name
- ) if job.assignedPrinter else
- I18N_CATALOG.i18nc("@info:status", "The print job '{job_name}' was finished.").format(
- job_name = job.name
- )),
- ).show()
-
- ## Updates the printer assignment for the given print job model.
- def _updateAssignedPrinter(self, model: UM3PrintJobOutputModel, printer_uuid: str) -> None:
- printer = next((p for p in self._printers if printer_uuid == p.key), None)
- if not printer:
- Logger.log("w", "Missing printer %s for job %s in %s", model.assignedPrinter, model.key,
- [p.key for p in self._printers])
- return
-
- printer.updateActivePrintJob(model)
- model.updateAssignedPrinter(printer)
-
- ## Uploads the mesh when the print job was registered with the cloud API.
- # \param job_response: The response received from the cloud API.
- def _onPrintJobCreated(self, job_response: CloudPrintJobResponse) -> None:
- self._progress.show()
- self._uploaded_print_job = job_response
- tool_path = cast(bytes, self._tool_path)
- self._api.uploadToolPath(job_response, tool_path, self._onPrintJobUploaded, self._progress.update, self._onUploadError)
-
- ## Requests the print to be sent to the printer when we finished uploading the mesh.
- def _onPrintJobUploaded(self) -> None:
- self._progress.update(100)
- print_job = cast(CloudPrintJobResponse, self._uploaded_print_job)
- self._api.requestPrint(self.key, print_job.job_id, self._onPrintUploadCompleted)
-
- ## Displays the given message if uploading the mesh has failed
- # \param message: The message to display.
- def _onUploadError(self, message: str = None) -> None:
- self._progress.hide()
- self._uploaded_print_job = None
- Message(
- text = message or I18N_CATALOG.i18nc("@info:text", "Could not upload the data to the printer."),
- title = I18N_CATALOG.i18nc("@info:title", "Cloud error"),
- lifetime = 10
- ).show()
- self.writeError.emit()
-
- ## Shows a message when the upload has succeeded
- # \param response: The response from the cloud API.
- def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None:
- Logger.log("d", "The cluster will be printing this print job with the ID %s", response.cluster_job_id)
- self._progress.hide()
- Message(
- text = I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
- title = I18N_CATALOG.i18nc("@info:title", "Data Sent"),
- lifetime = 5
- ).show()
- self.writeFinished.emit()
-
- ## Gets the remote printers.
- @pyqtProperty("QVariantList", notify=_clusterPrintersChanged)
- def printers(self) -> List[PrinterOutputModel]:
- return self._printers
-
- ## Get the active printer in the UI (monitor page).
- @pyqtProperty(QObject, notify = activePrinterChanged)
- def activePrinter(self) -> Optional[PrinterOutputModel]:
- return self._active_printer
-
- ## Set the active printer in the UI (monitor page).
- @pyqtSlot(QObject)
- def setActivePrinter(self, printer: Optional[PrinterOutputModel] = None) -> None:
- if printer != self._active_printer:
- self._active_printer = printer
- self.activePrinterChanged.emit()
-
- @pyqtProperty(int, notify = _clusterPrintersChanged)
- def clusterSize(self) -> int:
- return len(self._printers)
-
- ## Get remote print jobs.
- @pyqtProperty("QVariantList", notify = printJobsChanged)
- def printJobs(self) -> List[UM3PrintJobOutputModel]:
- return self._print_jobs
-
- ## Get remote print jobs that are still in the print queue.
- @pyqtProperty("QVariantList", notify = printJobsChanged)
- def queuedPrintJobs(self) -> List[UM3PrintJobOutputModel]:
- return [print_job for print_job in self._print_jobs
- if print_job.state == "queued" or print_job.state == "error"]
-
- ## Get remote print jobs that are assigned to a printer.
- @pyqtProperty("QVariantList", notify = printJobsChanged)
- def activePrintJobs(self) -> List[UM3PrintJobOutputModel]:
- return [print_job for print_job in self._print_jobs if
- print_job.assignedPrinter is not None and print_job.state != "queued"]
-
- @pyqtSlot(int, result = str)
- def formatDuration(self, seconds: int) -> str:
- return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
-
- @pyqtSlot(int, result = str)
- def getTimeCompleted(self, time_remaining: int) -> str:
- return formatTimeCompleted(time_remaining)
-
- @pyqtSlot(int, result = str)
- def getDateCompleted(self, time_remaining: int) -> str:
- return formatDateCompleted(time_remaining)
-
- ## TODO: The following methods are required by the monitor page QML, but are not actually available using cloud.
- # TODO: We fake the methods here to not break the monitor page.
-
- @pyqtProperty(QUrl, notify = _clusterPrintersChanged)
- def activeCameraUrl(self) -> "QUrl":
- return QUrl()
-
- @pyqtSlot(QUrl)
- def setActiveCameraUrl(self, camera_url: "QUrl") -> None:
- pass
-
- @pyqtProperty(bool, notify = printJobsChanged)
- def receivedPrintJobs(self) -> bool:
- return bool(self._print_jobs)
-
- @pyqtSlot()
- def openPrintJobControlPanel(self) -> None:
- pass
-
- @pyqtSlot()
- def openPrinterControlPanel(self) -> None:
- pass
-
- @pyqtSlot(str)
- def sendJobToTop(self, print_job_uuid: str) -> None:
- pass
-
- @pyqtSlot(str)
- def deleteJobFromQueue(self, print_job_uuid: str) -> None:
- pass
-
- @pyqtSlot(str)
- def forceSendJob(self, print_job_uuid: str) -> None:
- pass
-
- @pyqtProperty("QVariantList", notify = _clusterPrintersChanged)
- def connectedPrintersTypeCount(self) -> List[Dict[str, str]]:
- return []
+ ## Gets the URL on which to monitor the cluster via the cloud.
+ @property
+ def clusterCloudUrl(self) -> str:
+ root_url_prefix = "-staging" if self._account.is_staging else ""
+ return "https://mycloud{}.ultimaker.com/app/jobs/{}".format(root_url_prefix, self.clusterData.cluster_id)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
index e081beb99c..ccc64f8073 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
@@ -1,30 +1,29 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Dict, List
+from typing import Dict, List, Optional
from PyQt5.QtCore import QTimer
from UM import i18nCatalog
-from UM.Logger import Logger
-from UM.Message import Message
-from UM.Signal import Signal, signalemitter
+from UM.Logger import Logger # To log errors talking to the API.
+from UM.Signal import Signal
from cura.API import Account
from cura.CuraApplication import CuraApplication
+from cura.Settings.CuraStackBuilder import CuraStackBuilder
from cura.Settings.GlobalStack import GlobalStack
+
from .CloudApiClient import CloudApiClient
from .CloudOutputDevice import CloudOutputDevice
-from .Models.CloudClusterResponse import CloudClusterResponse
-from .Models.CloudError import CloudError
-from .Utils import findChanges
+from ..Models.Http.CloudClusterResponse import CloudClusterResponse
-## The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
-# Keeping all cloud related logic in this class instead of the UM3OutputDevicePlugin results in more readable code.
-#
-# API spec is available on https://api.ultimaker.com/docs/connect/spec/.
-#
+## The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
+# Keeping all cloud related logic in this class instead of the UM3OutputDevicePlugin results in more readable code.
+# API spec is available on https://api.ultimaker.com/docs/connect/spec/.
class CloudOutputDeviceManager:
+
META_CLUSTER_ID = "um_cloud_cluster_id"
+ META_NETWORK_KEY = "um_network_key"
# The interval with which the remote clusters are checked
CHECK_CLUSTER_INTERVAL = 30.0 # seconds
@@ -32,144 +31,154 @@ class CloudOutputDeviceManager:
# The translation catalog for this device.
I18N_CATALOG = i18nCatalog("cura")
- addedCloudCluster = Signal()
- removedCloudCluster = Signal()
+ # Signal emitted when the list of discovered devices changed.
+ discoveredDevicesChanged = Signal()
def __init__(self) -> None:
# Persistent dict containing the remote clusters for the authenticated user.
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice]
-
- self._application = CuraApplication.getInstance()
- self._output_device_manager = self._application.getOutputDeviceManager()
-
- self._account = self._application.getCuraAPI().account # type: Account
- self._api = CloudApiClient(self._account, self._onApiError)
+ self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
+ self._api = CloudApiClient(self._account, on_error = lambda error: Logger.log("e", str(error)))
+ self._account.loginStateChanged.connect(self._onLoginStateChanged)
# Create a timer to update the remote cluster list
self._update_timer = QTimer()
self._update_timer.setInterval(int(self.CHECK_CLUSTER_INTERVAL * 1000))
self._update_timer.setSingleShot(False)
+ self._update_timer.timeout.connect(self._getRemoteClusters)
+ # Ensure we don't start twice.
self._running = False
- # Called when the uses logs in or out
+ ## Starts running the cloud output device manager, thus periodically requesting cloud data.
+ def start(self):
+ if self._running:
+ return
+ if not self._account.isLoggedIn:
+ return
+ self._running = True
+ if not self._update_timer.isActive():
+ self._update_timer.start()
+ self._getRemoteClusters()
+
+ ## Stops running the cloud output device manager.
+ def stop(self):
+ if not self._running:
+ return
+ self._running = False
+ if self._update_timer.isActive():
+ self._update_timer.stop()
+ self._onGetRemoteClustersFinished([]) # Make sure we remove all cloud output devices.
+
+ ## Force refreshing connections.
+ def refreshConnections(self) -> None:
+ self._connectToActiveMachine()
+
+ ## Called when the uses logs in or out
def _onLoginStateChanged(self, is_logged_in: bool) -> None:
- Logger.log("d", "Log in state changed to %s", is_logged_in)
if is_logged_in:
- if not self._update_timer.isActive():
- self._update_timer.start()
- self._getRemoteClusters()
+ self.start()
else:
- if self._update_timer.isActive():
- self._update_timer.stop()
+ self.stop()
- # Notify that all clusters have disappeared
- self._onGetRemoteClustersFinished([])
-
- ## Gets all remote clusters from the API.
+ ## Gets all remote clusters from the API.
def _getRemoteClusters(self) -> None:
- Logger.log("d", "Retrieving remote clusters")
self._api.getClusters(self._onGetRemoteClustersFinished)
- ## Callback for when the request for getting the clusters. is finished.
+ ## Callback for when the request for getting the clusters is finished.
def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None:
online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse]
+ for device_id, cluster_data in online_clusters.items():
+ if device_id not in self._remote_clusters:
+ self._onDeviceDiscovered(cluster_data)
+ else:
+ self._onDiscoveredDeviceUpdated(cluster_data)
- removed_devices, added_clusters, updates = findChanges(self._remote_clusters, online_clusters)
-
- Logger.log("d", "Parsed remote clusters to %s", [cluster.toDict() for cluster in online_clusters.values()])
- Logger.log("d", "Removed: %s, added: %s, updates: %s", len(removed_devices), len(added_clusters), len(updates))
-
- # Remove output devices that are gone
- for removed_cluster in removed_devices:
- if removed_cluster.isConnected():
- removed_cluster.disconnect()
- removed_cluster.close()
- self._output_device_manager.removeOutputDevice(removed_cluster.key)
- self.removedCloudCluster.emit()
- del self._remote_clusters[removed_cluster.key]
-
- # Add an output device for each new remote cluster.
- # We only add when is_online as we don't want the option in the drop down if the cluster is not online.
- for added_cluster in added_clusters:
- device = CloudOutputDevice(self._api, added_cluster)
- self._remote_clusters[added_cluster.cluster_id] = device
- self.addedCloudCluster.emit()
-
- for device, cluster in updates:
- device.clusterData = cluster
+ removed_device_keys = set(self._remote_clusters.keys()) - set(online_clusters.keys())
+ for device_id in removed_device_keys:
+ self._onDiscoveredDeviceRemoved(device_id)
+ def _onDeviceDiscovered(self, cluster_data: CloudClusterResponse) -> None:
+ device = CloudOutputDevice(self._api, cluster_data)
+ CuraApplication.getInstance().getDiscoveredPrintersModel().addDiscoveredPrinter(
+ ip_address=device.key,
+ key=device.getId(),
+ name=device.getName(),
+ create_callback=self._createMachineFromDiscoveredDevice,
+ machine_type=device.printerType,
+ device=device
+ )
+ self._remote_clusters[device.getId()] = device
+ self.discoveredDevicesChanged.emit()
self._connectToActiveMachine()
+ def _onDiscoveredDeviceUpdated(self, cluster_data: CloudClusterResponse) -> None:
+ device = self._remote_clusters.get(cluster_data.cluster_id)
+ if not device:
+ return
+ CuraApplication.getInstance().getDiscoveredPrintersModel().updateDiscoveredPrinter(
+ ip_address=device.key,
+ name=cluster_data.friendly_name,
+ machine_type=device.printerType
+ )
+ self.discoveredDevicesChanged.emit()
+
+ def _onDiscoveredDeviceRemoved(self, device_id: str) -> None:
+ device = self._remote_clusters.pop(device_id, None) # type: Optional[CloudOutputDevice]
+ if not device:
+ return
+ device.close()
+ CuraApplication.getInstance().getDiscoveredPrintersModel().removeDiscoveredPrinter(device.key)
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+ if device.key in output_device_manager.getOutputDeviceIds():
+ output_device_manager.removeOutputDevice(device.key)
+ self.discoveredDevicesChanged.emit()
+
+ def _createMachineFromDiscoveredDevice(self, key: str) -> None:
+ device = self._remote_clusters[key]
+ if not device:
+ return
+
+ # Create a new machine and activate it.
+ # We do not use use MachineManager.addMachine here because we need to set the cluster ID before activating it.
+ new_machine = CuraStackBuilder.createMachine(device.name, device.printerType)
+ if not new_machine:
+ Logger.log("e", "Failed creating a new machine")
+ return
+ new_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
+ CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId())
+ self._connectToOutputDevice(device, new_machine)
+
## Callback for when the active machine was changed by the user or a new remote cluster was found.
def _connectToActiveMachine(self) -> None:
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine:
return
- # Remove all output devices that we have registered.
- # This is needed because when we switch machines we can only leave
- # output devices that are meant for that machine.
- for stored_cluster_id in self._remote_clusters:
- self._output_device_manager.removeOutputDevice(stored_cluster_id)
-
- # Check if the stored cluster_id for the active machine is in our list of remote clusters.
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
stored_cluster_id = active_machine.getMetaDataEntry(self.META_CLUSTER_ID)
- if stored_cluster_id in self._remote_clusters:
- device = self._remote_clusters[stored_cluster_id]
- self._connectToOutputDevice(device, active_machine)
- Logger.log("d", "Device connected by metadata cluster ID %s", stored_cluster_id)
- else:
- self._connectByNetworkKey(active_machine)
-
- ## Tries to match the local network key to the cloud cluster host name.
- def _connectByNetworkKey(self, active_machine: GlobalStack) -> None:
- # Check if the active printer has a local network connection and match this key to the remote cluster.
- local_network_key = active_machine.getMetaDataEntry("um_network_key")
- if not local_network_key:
- return
-
- device = next((c for c in self._remote_clusters.values() if c.matchesNetworkKey(local_network_key)), None)
- if not device:
- return
-
- Logger.log("i", "Found cluster %s with network key %s", device, local_network_key)
- active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
- self._connectToOutputDevice(device, active_machine)
+ local_network_key = active_machine.getMetaDataEntry(self.META_NETWORK_KEY)
+ for device in self._remote_clusters.values():
+ if device.key == stored_cluster_id:
+ # Connect to it if the stored ID matches.
+ self._connectToOutputDevice(device, active_machine)
+ elif local_network_key and device.matchesNetworkKey(local_network_key):
+ # Connect to it if we can match the local network key that was already present.
+ self._connectToOutputDevice(device, active_machine)
+ elif device.key in output_device_manager.getOutputDeviceIds():
+ # Remove device if it is not meant for the active machine.
+ output_device_manager.removeOutputDevice(device.key)
## Connects to an output device and makes sure it is registered in the output device manager.
- def _connectToOutputDevice(self, device: CloudOutputDevice, active_machine: GlobalStack) -> None:
- device.connect()
- self._output_device_manager.addOutputDevice(device)
- active_machine.addConfiguredConnectionType(device.connectionType.value)
+ def _connectToOutputDevice(self, device: CloudOutputDevice, machine: GlobalStack) -> None:
+ machine.setName(device.name)
+ machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
+ machine.setMetaDataEntry("group_name", device.name)
+ machine.addConfiguredConnectionType(device.connectionType.value)
- ## Handles an API error received from the cloud.
- # \param errors: The errors received
- def _onApiError(self, errors: List[CloudError] = None) -> None:
- Logger.log("w", str(errors))
- message = Message(
- text = self.I18N_CATALOG.i18nc("@info:description", "There was an error connecting to the cloud."),
- title = self.I18N_CATALOG.i18nc("@info:title", "Error"),
- lifetime = 10
- )
- message.show()
+ if not device.isConnected():
+ device.connect()
- ## Starts running the cloud output device manager, thus periodically requesting cloud data.
- def start(self):
- if self._running:
- return
- self._account.loginStateChanged.connect(self._onLoginStateChanged)
- # When switching machines we check if we have to activate a remote cluster.
- self._application.globalContainerStackChanged.connect(self._connectToActiveMachine)
- self._update_timer.timeout.connect(self._getRemoteClusters)
- self._onLoginStateChanged(is_logged_in = self._account.isLoggedIn)
-
- ## Stops running the cloud output device manager.
- def stop(self):
- if not self._running:
- return
- self._account.loginStateChanged.disconnect(self._onLoginStateChanged)
- # When switching machines we check if we have to activate a remote cluster.
- self._application.globalContainerStackChanged.disconnect(self._connectToActiveMachine)
- self._update_timer.timeout.disconnect(self._getRemoteClusters)
- self._onLoginStateChanged(is_logged_in = False)
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+ if device.key not in output_device_manager.getOutputDeviceIds():
+ output_device_manager.addOutputDevice(device)
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterBuildPlate.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterBuildPlate.py
deleted file mode 100644
index 4386bbb435..0000000000
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterBuildPlate.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from .BaseCloudModel import BaseCloudModel
-
-
-## Class representing a cluster printer
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterBuildPlate(BaseCloudModel):
- ## Create a new build plate
- # \param type: The type of buildplate glass or aluminium
- def __init__(self, type: str = "glass", **kwargs) -> None:
- self.type = type
- super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterConfigurationMaterial.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterConfigurationMaterial.py
deleted file mode 100644
index 652cbdabda..0000000000
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterConfigurationMaterial.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from typing import Optional
-
-from UM.Logger import Logger
-from cura.CuraApplication import CuraApplication
-from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
-from .BaseCloudModel import BaseCloudModel
-
-
-## Class representing a cloud cluster printer configuration
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrinterConfigurationMaterial(BaseCloudModel):
- ## Creates a new material configuration model.
- # \param brand: The brand of material in this print core, e.g. 'Ultimaker'.
- # \param color: The color of material in this print core, e.g. 'Blue'.
- # \param guid: he GUID of the material in this print core, e.g. '506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9'.
- # \param material: The type of material in this print core, e.g. 'PLA'.
- def __init__(self, brand: Optional[str] = None, color: Optional[str] = None, guid: Optional[str] = None,
- material: Optional[str] = None, **kwargs) -> None:
- self.guid = guid
- self.brand = brand
- self.color = color
- self.material = material
- super().__init__(**kwargs)
-
- ## Creates a material output model based on this cloud printer material.
- def createOutputModel(self) -> MaterialOutputModel:
- material_manager = CuraApplication.getInstance().getMaterialManager()
- material_group_list = material_manager.getMaterialGroupListByGUID(self.guid) or []
-
- # Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
- read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
- non_read_only_material_group_list = list(filter(lambda x: not x.is_read_only, material_group_list))
- material_group = None
- if read_only_material_group_list:
- read_only_material_group_list = sorted(read_only_material_group_list, key = lambda x: x.name)
- material_group = read_only_material_group_list[0]
- elif non_read_only_material_group_list:
- non_read_only_material_group_list = sorted(non_read_only_material_group_list, key = lambda x: x.name)
- material_group = non_read_only_material_group_list[0]
-
- if material_group:
- container = material_group.root_material_node.getContainer()
- color = container.getMetaDataEntry("color_code")
- brand = container.getMetaDataEntry("brand")
- material_type = container.getMetaDataEntry("material")
- name = container.getName()
- else:
- Logger.log("w", "Unable to find material with guid {guid}. Using data as provided by cluster"
- .format(guid = self.guid))
- color = self.color
- brand = self.brand
- material_type = self.material
- name = "Empty" if self.material == "empty" else "Unknown"
-
- return MaterialOutputModel(guid = self.guid, type = material_type, brand = brand, color = color, name = name)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterStatus.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterStatus.py
deleted file mode 100644
index bd3e482bde..0000000000
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterStatus.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from typing import List, Union, Dict, Optional, Any
-
-from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
-from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-from .CloudClusterBuildPlate import CloudClusterBuildPlate
-from .CloudClusterPrintCoreConfiguration import CloudClusterPrintCoreConfiguration
-from .BaseCloudModel import BaseCloudModel
-
-
-## Class representing a cluster printer
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrinterStatus(BaseCloudModel):
- ## Creates a new cluster printer status
- # \param enabled: A printer can be disabled if it should not receive new jobs. By default every printer is enabled.
- # \param firmware_version: Firmware version installed on the printer. Can differ for each printer in a cluster.
- # \param friendly_name: Human readable name of the printer. Can be used for identification purposes.
- # \param ip_address: The IP address of the printer in the local network.
- # \param machine_variant: The type of printer. Can be 'Ultimaker 3' or 'Ultimaker 3ext'.
- # \param status: The status of the printer.
- # \param unique_name: The unique name of the printer in the network.
- # \param uuid: The unique ID of the printer, also known as GUID.
- # \param configuration: The active print core configurations of this printer.
- # \param reserved_by: A printer can be claimed by a specific print job.
- # \param maintenance_required: Indicates if maintenance is necessary
- # \param firmware_update_status: Whether the printer's firmware is up-to-date, value is one of: "up_to_date",
- # "pending_update", "update_available", "update_in_progress", "update_failed", "update_impossible"
- # \param latest_available_firmware: The version of the latest firmware that is available
- # \param build_plate: The build plate that is on the printer
- def __init__(self, enabled: bool, firmware_version: str, friendly_name: str, ip_address: str, machine_variant: str,
- status: str, unique_name: str, uuid: str,
- configuration: List[Union[Dict[str, Any], CloudClusterPrintCoreConfiguration]],
- reserved_by: Optional[str] = None, maintenance_required: Optional[bool] = None,
- firmware_update_status: Optional[str] = None, latest_available_firmware: Optional[str] = None,
- build_plate: Union[Dict[str, Any], CloudClusterBuildPlate] = None, **kwargs) -> None:
-
- self.configuration = self.parseModels(CloudClusterPrintCoreConfiguration, configuration)
- self.enabled = enabled
- self.firmware_version = firmware_version
- self.friendly_name = friendly_name
- self.ip_address = ip_address
- self.machine_variant = machine_variant
- self.status = status
- self.unique_name = unique_name
- self.uuid = uuid
- self.reserved_by = reserved_by
- self.maintenance_required = maintenance_required
- self.firmware_update_status = firmware_update_status
- self.latest_available_firmware = latest_available_firmware
- self.build_plate = self.parseModel(CloudClusterBuildPlate, build_plate) if build_plate else None
- super().__init__(**kwargs)
-
- ## Creates a new output model.
- # \param controller - The controller of the model.
- def createOutputModel(self, controller: PrinterOutputController) -> PrinterOutputModel:
- model = PrinterOutputModel(controller, len(self.configuration), firmware_version = self.firmware_version)
- self.updateOutputModel(model)
- return model
-
- ## Updates the given output model.
- # \param model - The output model to update.
- def updateOutputModel(self, model: PrinterOutputModel) -> None:
- model.updateKey(self.uuid)
- model.updateName(self.friendly_name)
- model.updateType(self.machine_variant)
- model.updateState(self.status if self.enabled else "disabled")
- model.updateBuildplate(self.build_plate.type if self.build_plate else "glass")
-
- for configuration, extruder_output, extruder_config in \
- zip(self.configuration, model.extruders, model.printerConfiguration.extruderConfigurations):
- configuration.updateOutputModel(extruder_output)
- configuration.updateConfigurationModel(extruder_config)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py
deleted file mode 100644
index f3f6970c54..0000000000
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py b/plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py
index 176b7e6ab7..d5de7fe10a 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py
+++ b/plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QUrl
@@ -6,7 +6,8 @@ from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManage
from typing import Optional, Callable, Any, Tuple, cast
from UM.Logger import Logger
-from .Models.CloudPrintJobResponse import CloudPrintJobResponse
+
+from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse
## Class responsible for uploading meshes to the cloud in separate requests.
@@ -53,7 +54,7 @@ class ToolPathUploader:
def _createRequest(self) -> QNetworkRequest:
request = QNetworkRequest(QUrl(self._print_job.upload_url))
request.setHeader(QNetworkRequest.ContentTypeHeader, self._print_job.content_type)
-
+
first_byte, last_byte = self._chunkRange()
content_range = "bytes {}-{}/{}".format(first_byte, last_byte - 1, len(self._data))
request.setRawHeader(b"Content-Range", content_range.encode())
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Utils.py b/plugins/UM3NetworkPrinting/src/Cloud/Utils.py
deleted file mode 100644
index 5136e0e7db..0000000000
--- a/plugins/UM3NetworkPrinting/src/Cloud/Utils.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from datetime import datetime, timedelta
-from typing import TypeVar, Dict, Tuple, List
-
-from UM import i18nCatalog
-
-T = TypeVar("T")
-U = TypeVar("U")
-
-
-## Splits the given dictionaries into three lists (in a tuple):
-# - `removed`: Items that were in the first argument but removed in the second one.
-# - `added`: Items that were not in the first argument but were included in the second one.
-# - `updated`: Items that were in both dictionaries. Both values are given in a tuple.
-# \param previous: The previous items
-# \param received: The received items
-# \return: The tuple (removed, added, updated) as explained above.
-def findChanges(previous: Dict[str, T], received: Dict[str, U]) -> Tuple[List[T], List[U], List[Tuple[T, U]]]:
- previous_ids = set(previous)
- received_ids = set(received)
-
- removed_ids = previous_ids.difference(received_ids)
- new_ids = received_ids.difference(previous_ids)
- updated_ids = received_ids.intersection(previous_ids)
-
- removed = [previous[removed_id] for removed_id in removed_ids]
- added = [received[new_id] for new_id in new_ids]
- updated = [(previous[updated_id], received[updated_id]) for updated_id in updated_ids]
-
- return removed, added, updated
-
-
-def formatTimeCompleted(seconds_remaining: int) -> str:
- completed = datetime.now() + timedelta(seconds=seconds_remaining)
- return "{hour:02d}:{minute:02d}".format(hour = completed.hour, minute = completed.minute)
-
-
-def formatDateCompleted(seconds_remaining: int) -> str:
- now = datetime.now()
- completed = now + timedelta(seconds=seconds_remaining)
- days = (completed.date() - now.date()).days
- i18n = i18nCatalog("cura")
-
- # If finishing date is more than 7 days out, using "Mon Dec 3 at HH:MM" format
- if days >= 7:
- return completed.strftime("%a %b ") + "{day}".format(day = completed.day)
- # If finishing date is within the next week, use "Monday at HH:MM" format
- elif days >= 2:
- return completed.strftime("%a")
- # If finishing tomorrow, use "tomorrow at HH:MM" format
- elif days >= 1:
- return i18n.i18nc("@info:status", "tomorrow")
- # If finishing today, use "today at HH:MM" format
- else:
- return i18n.i18nc("@info:status", "today")
diff --git a/plugins/UM3NetworkPrinting/src/ClusterOutputController.py b/plugins/UM3NetworkPrinting/src/ClusterOutputController.py
new file mode 100644
index 0000000000..02d8d174d1
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/ClusterOutputController.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
+from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+
+
+class ClusterOutputController(PrinterOutputController):
+
+ def __init__(self, output_device: PrinterOutputDevice) -> None:
+ super().__init__(output_device)
+ self.can_pause = True
+ self.can_abort = True
+ self.can_pre_heat_bed = False
+ self.can_pre_heat_hotends = False
+ self.can_send_raw_gcode = False
+ self.can_control_manually = False
+ self.can_update_firmware = False
+
+ def setJobState(self, job: PrintJobOutputModel, state: str):
+ self._output_device.setJobState(job.key, state)
diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py
deleted file mode 100644
index c7dd33f1fc..0000000000
--- a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py
+++ /dev/null
@@ -1,705 +0,0 @@
-# Copyright (c) 2019 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from typing import Any, cast, Tuple, Union, Optional, Dict, List
-from time import time
-
-import io # To create the correct buffers for sending data to the printer.
-import json
-import os
-
-from UM.FileHandler.FileHandler import FileHandler
-from UM.FileHandler.WriteFileJob import WriteFileJob # To call the file writer asynchronously.
-from UM.i18n import i18nCatalog
-from UM.Logger import Logger
-from UM.Message import Message
-from UM.PluginRegistry import PluginRegistry
-from UM.Qt.Duration import Duration, DurationFormat
-from UM.Scene.SceneNode import SceneNode # For typing.
-from UM.Settings.ContainerRegistry import ContainerRegistry
-
-from cura.CuraApplication import CuraApplication
-from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
-from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
-from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
-from cura.PrinterOutputDevice import ConnectionType
-
-from .Cloud.Utils import formatTimeCompleted, formatDateCompleted
-from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
-from .ConfigurationChangeModel import ConfigurationChangeModel
-from .MeshFormatHandler import MeshFormatHandler
-from .SendMaterialJob import SendMaterialJob
-from .UM3PrintJobOutputModel import UM3PrintJobOutputModel
-
-from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
-from PyQt5.QtGui import QDesktopServices, QImage
-from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
-
-i18n_catalog = i18nCatalog("cura")
-
-
-class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
- printJobsChanged = pyqtSignal()
- activePrinterChanged = pyqtSignal()
- activeCameraUrlChanged = pyqtSignal()
- receivedPrintJobsChanged = pyqtSignal()
-
- # Notify can only use signals that are defined by the class that they are in, not inherited ones.
- # Therefore we create a private signal used to trigger the printersChanged signal.
- _clusterPrintersChanged = pyqtSignal()
-
- def __init__(self, device_id, address, properties, parent = None) -> None:
- super().__init__(device_id = device_id, address = address, properties=properties, connection_type = ConnectionType.NetworkConnection, parent = parent)
- self._api_prefix = "/cluster-api/v1/"
-
- self._application = CuraApplication.getInstance()
-
- self._number_of_extruders = 2
-
- self._dummy_lambdas = (
- "", {}, io.BytesIO()
- ) # type: Tuple[Optional[str], Dict[str, Union[str, int, bool]], Union[io.StringIO, io.BytesIO]]
-
- self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
- self._received_print_jobs = False # type: bool
-
- if PluginRegistry.getInstance() is not None:
- self._monitor_view_qml_path = os.path.join(
- PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
- "resources", "qml", "MonitorStage.qml"
- )
-
- # Trigger the printersChanged signal when the private signal is triggered
- self.printersChanged.connect(self._clusterPrintersChanged)
-
- self._accepts_commands = True # type: bool
-
- # Cluster does not have authentication, so default to authenticated
- self._authentication_state = AuthState.Authenticated
-
- self._error_message = None # type: Optional[Message]
- self._write_job_progress_message = None # type: Optional[Message]
- self._progress_message = None # type: Optional[Message]
-
- self._active_printer = None # type: Optional[PrinterOutputModel]
-
- self._printer_selection_dialog = None # type: QObject
-
- self.setPriority(3) # Make sure the output device gets selected above local file output
- self.setName(self._id)
- self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
- self.setDescription(i18n_catalog.i18nc("@properties:tooltip", "Print over network"))
-
- self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network"))
-
- self._printer_uuid_to_unique_name_mapping = {} # type: Dict[str, str]
-
- self._finished_jobs = [] # type: List[UM3PrintJobOutputModel]
-
- self._cluster_size = int(properties.get(b"cluster_size", 0)) # type: int
-
- self._latest_reply_handler = None # type: Optional[QNetworkReply]
- self._sending_job = None
-
- self._active_camera_url = QUrl() # type: QUrl
-
- def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
- file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
- self.writeStarted.emit(self)
-
- self.sendMaterialProfiles()
-
- mesh_format = MeshFormatHandler(file_handler, self.firmwareVersion)
-
- # This function pauses with the yield, waiting on instructions on which printer it needs to print with.
- if not mesh_format.is_valid:
- Logger.log("e", "Missing file or mesh writer!")
- return
- self._sending_job = self._sendPrintJob(mesh_format, nodes)
- if self._sending_job is not None:
- self._sending_job.send(None) # Start the generator.
-
- if len(self._printers) > 1: # We need to ask the user.
- self._spawnPrinterSelectionDialog()
- is_job_sent = True
- else: # Just immediately continue.
- self._sending_job.send("") # No specifically selected printer.
- is_job_sent = self._sending_job.send(None)
-
- def _spawnPrinterSelectionDialog(self):
- if self._printer_selection_dialog is None:
- if PluginRegistry.getInstance() is not None:
- path = os.path.join(
- PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
- "resources", "qml", "PrintWindow.qml"
- )
- self._printer_selection_dialog = self._application.createQmlComponent(path, {"OutputDevice": self})
- if self._printer_selection_dialog is not None:
- self._printer_selection_dialog.show()
-
- @pyqtProperty(int, constant=True)
- def clusterSize(self) -> int:
- return self._cluster_size
-
- ## Allows the user to choose a printer to print with from the printer
- # selection dialogue.
- # \param target_printer The name of the printer to target.
- @pyqtSlot(str)
- def selectPrinter(self, target_printer: str = "") -> None:
- if self._sending_job is not None:
- self._sending_job.send(target_printer)
-
- @pyqtSlot()
- def cancelPrintSelection(self) -> None:
- self._sending_gcode = False
-
- ## Greenlet to send a job to the printer over the network.
- #
- # This greenlet gets called asynchronously in requestWrite. It is a
- # greenlet in order to optionally wait for selectPrinter() to select a
- # printer.
- # The greenlet yields exactly three times: First time None,
- # \param mesh_format Object responsible for choosing the right kind of format to write with.
- def _sendPrintJob(self, mesh_format: MeshFormatHandler, nodes: List[SceneNode]):
- Logger.log("i", "Sending print job to printer.")
- if self._sending_gcode:
- self._error_message = Message(
- i18n_catalog.i18nc("@info:status",
- "Sending new jobs (temporarily) blocked, still sending the previous print job."))
- self._error_message.show()
- yield #Wait on the user to select a target printer.
- yield #Wait for the write job to be finished.
- yield False #Return whether this was a success or not.
- yield #Prevent StopIteration.
-
- self._sending_gcode = True
-
- # Potentially wait on the user to select a target printer.
- target_printer = yield # type: Optional[str]
-
- # Using buffering greatly reduces the write time for many lines of gcode
-
- stream = mesh_format.createStream()
-
- job = WriteFileJob(mesh_format.writer, stream, nodes, mesh_format.file_mode)
-
- self._write_job_progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"),
- lifetime = 0, dismissable = False, progress = -1,
- title = i18n_catalog.i18nc("@info:title", "Sending Data"),
- use_inactivity_timer = False)
- self._write_job_progress_message.show()
-
- if mesh_format.preferred_format is not None:
- self._dummy_lambdas = (target_printer, mesh_format.preferred_format, stream)
- job.finished.connect(self._sendPrintJobWaitOnWriteJobFinished)
- job.start()
- yield True # Return that we had success!
- yield # To prevent having to catch the StopIteration exception.
-
- def _sendPrintJobWaitOnWriteJobFinished(self, job: WriteFileJob) -> None:
- if self._write_job_progress_message:
- self._write_job_progress_message.hide()
-
- self._progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0,
- dismissable = False, progress = -1,
- title = i18n_catalog.i18nc("@info:title", "Sending Data"))
- self._progress_message.addAction("Abort", i18n_catalog.i18nc("@action:button", "Cancel"), icon = "",
- description = "")
- self._progress_message.actionTriggered.connect(self._progressMessageActionTriggered)
- self._progress_message.show()
- parts = []
-
- target_printer, preferred_format, stream = self._dummy_lambdas
-
- # If a specific printer was selected, it should be printed with that machine.
- if target_printer:
- target_printer = self._printer_uuid_to_unique_name_mapping[target_printer]
- parts.append(self._createFormPart("name=require_printer_name", bytes(target_printer, "utf-8"), "text/plain"))
-
- # Add user name to the print_job
- parts.append(self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain"))
-
- file_name = self._application.getPrintInformation().jobName + "." + preferred_format["extension"]
-
- output = stream.getvalue() # Either str or bytes depending on the output mode.
- if isinstance(stream, io.StringIO):
- output = cast(str, output).encode("utf-8")
- output = cast(bytes, output)
-
- parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % file_name, output))
-
- self._latest_reply_handler = self.postFormWithParts("print_jobs/", parts,
- on_finished = self._onPostPrintJobFinished,
- on_progress = self._onUploadPrintJobProgress)
-
- @pyqtProperty(QObject, notify = activePrinterChanged)
- def activePrinter(self) -> Optional[PrinterOutputModel]:
- return self._active_printer
-
- @pyqtSlot(QObject)
- def setActivePrinter(self, printer: Optional[PrinterOutputModel]) -> None:
- if self._active_printer != printer:
- self._active_printer = printer
- self.activePrinterChanged.emit()
-
- @pyqtProperty(QUrl, notify = activeCameraUrlChanged)
- def activeCameraUrl(self) -> "QUrl":
- return self._active_camera_url
-
- @pyqtSlot(QUrl)
- def setActiveCameraUrl(self, camera_url: "QUrl") -> None:
- if self._active_camera_url != camera_url:
- self._active_camera_url = camera_url
- self.activeCameraUrlChanged.emit()
-
- def _onPostPrintJobFinished(self, reply: QNetworkReply) -> None:
- if self._progress_message:
- self._progress_message.hide()
- self._compressing_gcode = False
- self._sending_gcode = False
-
- ## The IP address of the printer.
- @pyqtProperty(str, constant = True)
- def address(self) -> str:
- return self._address
-
- def _onUploadPrintJobProgress(self, bytes_sent: int, bytes_total: int) -> None:
- if bytes_total > 0:
- new_progress = bytes_sent / bytes_total * 100
- # Treat upload progress as response. Uploading can take more than 10 seconds, so if we don't, we can get
- # timeout responses if this happens.
- self._last_response_time = time()
- if self._progress_message is not None and new_progress != self._progress_message.getProgress():
- self._progress_message.show() # Ensure that the message is visible.
- self._progress_message.setProgress(bytes_sent / bytes_total * 100)
-
- # If successfully sent:
- if bytes_sent == bytes_total:
- # Show a confirmation to the user so they know the job was sucessful and provide the option to switch to
- # the monitor tab.
- self._success_message = Message(
- i18n_catalog.i18nc("@info:status", "Print job was successfully sent to the printer."),
- lifetime=5, dismissable=True,
- title=i18n_catalog.i18nc("@info:title", "Data Sent"))
- self._success_message.addAction("View", i18n_catalog.i18nc("@action:button", "View in Monitor"), icon = "",
- description="")
- self._success_message.actionTriggered.connect(self._successMessageActionTriggered)
- self._success_message.show()
- else:
- if self._progress_message is not None:
- self._progress_message.setProgress(0)
- self._progress_message.hide()
-
- def _progressMessageActionTriggered(self, message_id: Optional[str] = None, action_id: Optional[str] = None) -> None:
- if action_id == "Abort":
- Logger.log("d", "User aborted sending print to remote.")
- if self._progress_message is not None:
- self._progress_message.hide()
- self._compressing_gcode = False
- self._sending_gcode = False
- self._application.getController().setActiveStage("PrepareStage")
-
- # After compressing the sliced model Cura sends data to printer, to stop receiving updates from the request
- # the "reply" should be disconnected
- if self._latest_reply_handler:
- self._latest_reply_handler.disconnect()
- self._latest_reply_handler = None
-
- def _successMessageActionTriggered(self, message_id: Optional[str] = None, action_id: Optional[str] = None) -> None:
- if action_id == "View":
- self._application.getController().setActiveStage("MonitorStage")
-
- @pyqtSlot()
- def openPrintJobControlPanel(self) -> None:
- Logger.log("d", "Opening print job control panel...")
- QDesktopServices.openUrl(QUrl("http://" + self._address + "/print_jobs"))
-
- @pyqtSlot()
- def openPrinterControlPanel(self) -> None:
- Logger.log("d", "Opening printer control panel...")
- QDesktopServices.openUrl(QUrl("http://" + self._address + "/printers"))
-
- @pyqtProperty("QVariantList", notify = printJobsChanged)
- def printJobs(self)-> List[UM3PrintJobOutputModel]:
- return self._print_jobs
-
- @pyqtProperty(bool, notify = receivedPrintJobsChanged)
- def receivedPrintJobs(self) -> bool:
- return self._received_print_jobs
-
- @pyqtProperty("QVariantList", notify = printJobsChanged)
- def queuedPrintJobs(self) -> List[UM3PrintJobOutputModel]:
- return [print_job for print_job in self._print_jobs if print_job.state == "queued" or print_job.state == "error"]
-
- @pyqtProperty("QVariantList", notify = printJobsChanged)
- def activePrintJobs(self) -> List[UM3PrintJobOutputModel]:
- return [print_job for print_job in self._print_jobs if print_job.assignedPrinter is not None and print_job.state != "queued"]
-
- @pyqtProperty("QVariantList", notify = _clusterPrintersChanged)
- def connectedPrintersTypeCount(self) -> List[Dict[str, str]]:
- printer_count = {} # type: Dict[str, int]
- for printer in self._printers:
- if printer.type in printer_count:
- printer_count[printer.type] += 1
- else:
- printer_count[printer.type] = 1
- result = []
- for machine_type in printer_count:
- result.append({"machine_type": machine_type, "count": str(printer_count[machine_type])})
- return result
-
- @pyqtProperty("QVariantList", notify=_clusterPrintersChanged)
- def printers(self):
- return self._printers
-
- @pyqtSlot(int, result = str)
- def getTimeCompleted(self, time_remaining: int) -> str:
- return formatTimeCompleted(time_remaining)
-
- @pyqtSlot(int, result = str)
- def getDateCompleted(self, time_remaining: int) -> str:
- return formatDateCompleted(time_remaining)
-
- @pyqtSlot(int, result = str)
- def formatDuration(self, seconds: int) -> str:
- return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
-
- @pyqtSlot(str)
- def sendJobToTop(self, print_job_uuid: str) -> None:
- # This function is part of the output device (and not of the printjob output model) as this type of operation
- # is a modification of the cluster queue and not of the actual job.
- data = "{\"to_position\": 0}"
- self.put("print_jobs/{uuid}/move_to_position".format(uuid = print_job_uuid), data, on_finished=None)
-
- @pyqtSlot(str)
- def deleteJobFromQueue(self, print_job_uuid: str) -> None:
- # This function is part of the output device (and not of the printjob output model) as this type of operation
- # is a modification of the cluster queue and not of the actual job.
- self.delete("print_jobs/{uuid}".format(uuid = print_job_uuid), on_finished=None)
-
- @pyqtSlot(str)
- def forceSendJob(self, print_job_uuid: str) -> None:
- data = "{\"force\": true}"
- self.put("print_jobs/{uuid}".format(uuid=print_job_uuid), data, on_finished=None)
-
- def _printJobStateChanged(self) -> None:
- username = self._getUserName()
-
- if username is None:
- return # We only want to show notifications if username is set.
-
- finished_jobs = [job for job in self._print_jobs if job.state == "wait_cleanup"]
-
- newly_finished_jobs = [job for job in finished_jobs if job not in self._finished_jobs and job.owner == username]
- for job in newly_finished_jobs:
- if job.assignedPrinter:
- job_completed_text = i18n_catalog.i18nc("@info:status", "Printer '{printer_name}' has finished printing '{job_name}'.".format(printer_name=job.assignedPrinter.name, job_name = job.name))
- else:
- job_completed_text = i18n_catalog.i18nc("@info:status", "The print job '{job_name}' was finished.".format(job_name = job.name))
- job_completed_message = Message(text=job_completed_text, title = i18n_catalog.i18nc("@info:status", "Print finished"))
- job_completed_message.show()
-
- # Ensure UI gets updated
- self.printJobsChanged.emit()
-
- # Keep a list of all completed jobs so we know if something changed next time.
- self._finished_jobs = finished_jobs
-
- ## Called when the connection to the cluster changes.
- def connect(self) -> None:
- super().connect()
- self.sendMaterialProfiles()
-
- def _onGetPreviewImageFinished(self, reply: QNetworkReply) -> None:
- reply_url = reply.url().toString()
-
- uuid = reply_url[reply_url.find("print_jobs/")+len("print_jobs/"):reply_url.rfind("/preview_image")]
-
- print_job = findByKey(self._print_jobs, uuid)
- if print_job:
- image = QImage()
- image.loadFromData(reply.readAll())
- print_job.updatePreviewImage(image)
-
- def _update(self) -> None:
- super()._update()
- self.get("printers/", on_finished = self._onGetPrintersDataFinished)
- self.get("print_jobs/", on_finished = self._onGetPrintJobsFinished)
-
- for print_job in self._print_jobs:
- if print_job.getPreviewImage() is None:
- self.get("print_jobs/{uuid}/preview_image".format(uuid=print_job.key), on_finished=self._onGetPreviewImageFinished)
-
- def _onGetPrintJobsFinished(self, reply: QNetworkReply) -> None:
- self._received_print_jobs = True
- self.receivedPrintJobsChanged.emit()
-
- if not checkValidGetReply(reply):
- return
-
- result = loadJsonFromReply(reply)
- if result is None:
- return
-
- print_jobs_seen = []
- job_list_changed = False
- for idx, print_job_data in enumerate(result):
- print_job = findByKey(self._print_jobs, print_job_data["uuid"])
- if print_job is None:
- print_job = self._createPrintJobModel(print_job_data)
- job_list_changed = True
- elif not job_list_changed:
- # Check if the order of the jobs has changed since the last check
- if self._print_jobs.index(print_job) != idx:
- job_list_changed = True
-
- self._updatePrintJob(print_job, print_job_data)
-
- if print_job.state != "queued" and print_job.state != "error": # Print job should be assigned to a printer.
- if print_job.state in ["failed", "finished", "aborted", "none"]:
- # Print job was already completed, so don't attach it to a printer.
- printer = None
- else:
- printer = self._getPrinterByKey(print_job_data["printer_uuid"])
- else: # The job can "reserve" a printer if some changes are required.
- printer = self._getPrinterByKey(print_job_data["assigned_to"])
-
- if printer:
- printer.updateActivePrintJob(print_job)
-
- print_jobs_seen.append(print_job)
-
- # Check what jobs need to be removed.
- removed_jobs = [print_job for print_job in self._print_jobs if print_job not in print_jobs_seen]
-
- for removed_job in removed_jobs:
- job_list_changed = job_list_changed or self._removeJob(removed_job)
-
- if job_list_changed:
- # Override the old list with the new list (either because jobs were removed / added or order changed)
- self._print_jobs = print_jobs_seen
- self.printJobsChanged.emit() # Do a single emit for all print job changes.
-
- def _onGetPrintersDataFinished(self, reply: QNetworkReply) -> None:
- if not checkValidGetReply(reply):
- return
-
- result = loadJsonFromReply(reply)
- if result is None:
- return
-
- printer_list_changed = False
- printers_seen = []
-
- for printer_data in result:
- printer = findByKey(self._printers, printer_data["uuid"])
-
- if printer is None:
- printer = self._createPrinterModel(printer_data)
- printer_list_changed = True
-
- printers_seen.append(printer)
-
- self._updatePrinter(printer, printer_data)
-
- removed_printers = [printer for printer in self._printers if printer not in printers_seen]
- for printer in removed_printers:
- self._removePrinter(printer)
-
- if removed_printers or printer_list_changed:
- self.printersChanged.emit()
-
- def _createPrinterModel(self, data: Dict[str, Any]) -> PrinterOutputModel:
- printer = PrinterOutputModel(output_controller = ClusterUM3PrinterOutputController(self),
- number_of_extruders = self._number_of_extruders)
- printer.setCameraUrl(QUrl("http://" + data["ip_address"] + ":8080/?action=stream"))
- self._printers.append(printer)
- return printer
-
- def _createPrintJobModel(self, data: Dict[str, Any]) -> UM3PrintJobOutputModel:
- print_job = UM3PrintJobOutputModel(output_controller=ClusterUM3PrinterOutputController(self),
- key=data["uuid"], name= data["name"])
-
- configuration = ConfigurationModel()
- extruders = [ExtruderConfigurationModel(position = idx) for idx in range(0, self._number_of_extruders)]
- for index in range(0, self._number_of_extruders):
- try:
- extruder_data = data["configuration"][index]
- except IndexError:
- continue
- extruder = extruders[int(data["configuration"][index]["extruder_index"])]
- extruder.setHotendID(extruder_data.get("print_core_id", ""))
- extruder.setMaterial(self._createMaterialOutputModel(extruder_data.get("material", {})))
-
- configuration.setExtruderConfigurations(extruders)
- print_job.updateConfiguration(configuration)
- print_job.setCompatibleMachineFamilies(data.get("compatible_machine_families", []))
- print_job.stateChanged.connect(self._printJobStateChanged)
- return print_job
-
- def _updatePrintJob(self, print_job: UM3PrintJobOutputModel, data: Dict[str, Any]) -> None:
- print_job.updateTimeTotal(data["time_total"])
- print_job.updateTimeElapsed(data["time_elapsed"])
- impediments_to_printing = data.get("impediments_to_printing", [])
- print_job.updateOwner(data["owner"])
-
- status_set_by_impediment = False
- for impediment in impediments_to_printing:
- if impediment["severity"] == "UNFIXABLE":
- status_set_by_impediment = True
- print_job.updateState("error")
- break
-
- if not status_set_by_impediment:
- print_job.updateState(data["status"])
-
- print_job.updateConfigurationChanges(self._createConfigurationChanges(data["configuration_changes_required"]))
-
- def _createConfigurationChanges(self, data: List[Dict[str, Any]]) -> List[ConfigurationChangeModel]:
- result = []
- for change in data:
- result.append(ConfigurationChangeModel(type_of_change=change["type_of_change"],
- index=change["index"],
- target_name=change["target_name"],
- origin_name=change["origin_name"]))
- return result
-
- def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel":
- material_manager = self._application.getMaterialManager()
- material_group_list = None
-
- # Avoid crashing if there is no "guid" field in the metadata
- material_guid = material_data.get("guid")
- if material_guid:
- material_group_list = material_manager.getMaterialGroupListByGUID(material_guid)
-
- # This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the
- # material is unknown to Cura, so we should return an "empty" or "unknown" material model.
- if material_group_list is None:
- material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
- else i18n_catalog.i18nc("@label:material", "Unknown")
-
- return MaterialOutputModel(guid = material_data.get("guid", ""),
- type = material_data.get("material", ""),
- color = material_data.get("color", ""),
- brand = material_data.get("brand", ""),
- name = material_data.get("name", material_name)
- )
-
- # Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
- read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
- non_read_only_material_group_list = list(filter(lambda x: not x.is_read_only, material_group_list))
- material_group = None
- if read_only_material_group_list:
- read_only_material_group_list = sorted(read_only_material_group_list, key = lambda x: x.name)
- material_group = read_only_material_group_list[0]
- elif non_read_only_material_group_list:
- non_read_only_material_group_list = sorted(non_read_only_material_group_list, key = lambda x: x.name)
- material_group = non_read_only_material_group_list[0]
-
- if material_group:
- container = material_group.root_material_node.getContainer()
- color = container.getMetaDataEntry("color_code")
- brand = container.getMetaDataEntry("brand")
- material_type = container.getMetaDataEntry("material")
- name = container.getName()
- else:
- Logger.log("w",
- "Unable to find material with guid {guid}. Using data as provided by cluster".format(
- guid=material_data["guid"]))
- color = material_data["color"]
- brand = material_data["brand"]
- material_type = material_data["material"]
- name = i18n_catalog.i18nc("@label:material", "Empty") if material_data["material"] == "empty" \
- else i18n_catalog.i18nc("@label:material", "Unknown")
- return MaterialOutputModel(guid = material_data["guid"], type = material_type,
- brand = brand, color = color, name = name)
-
- def _updatePrinter(self, printer: PrinterOutputModel, data: Dict[str, Any]) -> None:
- # For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer.
- # Then we suddenly need the unique name. So in order to not have to mess up all the other code, we save a mapping.
- self._printer_uuid_to_unique_name_mapping[data["uuid"]] = data["unique_name"]
-
- definitions = ContainerRegistry.getInstance().findDefinitionContainers(name = data["machine_variant"])
- if not definitions:
- Logger.log("w", "Unable to find definition for machine variant %s", data["machine_variant"])
- return
-
- machine_definition = definitions[0]
-
- printer.updateName(data["friendly_name"])
- printer.updateKey(data["uuid"])
- printer.updateType(data["machine_variant"])
-
- # Do not store the build plate information that comes from connect if the current printer has not build plate information
- if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):
- printer.updateBuildplate(data["build_plate"]["type"])
- if not data["enabled"]:
- printer.updateState("disabled")
- else:
- printer.updateState(data["status"])
-
- for index in range(0, self._number_of_extruders):
- extruder = printer.extruders[index]
- try:
- extruder_data = data["configuration"][index]
- except IndexError:
- break
-
- extruder.updateHotendID(extruder_data.get("print_core_id", ""))
-
- material_data = extruder_data["material"]
- if extruder.activeMaterial is None or extruder.activeMaterial.guid != material_data["guid"]:
- material = self._createMaterialOutputModel(material_data)
- extruder.updateActiveMaterial(material)
-
- def _removeJob(self, job: UM3PrintJobOutputModel) -> bool:
- if job not in self._print_jobs:
- return False
-
- if job.assignedPrinter:
- job.assignedPrinter.updateActivePrintJob(None)
- job.stateChanged.disconnect(self._printJobStateChanged)
- self._print_jobs.remove(job)
-
- return True
-
- def _removePrinter(self, printer: PrinterOutputModel) -> None:
- self._printers.remove(printer)
- if self._active_printer == printer:
- self._active_printer = None
- self.activePrinterChanged.emit()
-
- ## Sync the material profiles in Cura with the printer.
- #
- # This gets called when connecting to a printer as well as when sending a
- # print.
- def sendMaterialProfiles(self) -> None:
- job = SendMaterialJob(device = self)
- job.run()
-
-def loadJsonFromReply(reply: QNetworkReply) -> Optional[List[Dict[str, Any]]]:
- try:
- result = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except json.decoder.JSONDecodeError:
- Logger.logException("w", "Unable to decode JSON from reply.")
- return None
- return result
-
-
-def checkValidGetReply(reply: QNetworkReply) -> bool:
- status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
-
- if status_code != 200:
- Logger.log("w", "Got status code {status_code} while trying to get data".format(status_code=status_code))
- return False
- return True
-
-
-def findByKey(lst: List[Union[UM3PrintJobOutputModel, PrinterOutputModel]], key: str) -> Optional[UM3PrintJobOutputModel]:
- for item in lst:
- if item.key == key:
- return item
- return None
diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py b/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py
deleted file mode 100644
index fc6798386a..0000000000
--- a/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
-
-MYPY = False
-if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
-
-class ClusterUM3PrinterOutputController(PrinterOutputController):
- def __init__(self, output_device):
- super().__init__(output_device)
- self.can_pre_heat_bed = False
- self.can_pre_heat_hotends = False
- self.can_control_manually = False
- self.can_send_raw_gcode = False
-
- def setJobState(self, job: "PrintJobOutputModel", state: str):
- data = "{\"action\": \"%s\"}" % state
- self._output_device.put("print_jobs/%s/action" % job.key, data, on_finished=None)
diff --git a/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py b/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py
deleted file mode 100644
index ecc89b3948..0000000000
--- a/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-import os.path
-import time
-from typing import Optional, TYPE_CHECKING
-
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject
-
-from UM.PluginRegistry import PluginRegistry
-from UM.Logger import Logger
-from UM.i18n import i18nCatalog
-
-from cura.CuraApplication import CuraApplication
-from cura.MachineAction import MachineAction
-from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
-
-from .UM3OutputDevicePlugin import UM3OutputDevicePlugin
-
-if TYPE_CHECKING:
- from cura.PrinterOutputDevice import PrinterOutputDevice
-
-catalog = i18nCatalog("cura")
-
-
-class DiscoverUM3Action(MachineAction):
- discoveredDevicesChanged = pyqtSignal()
-
- def __init__(self) -> None:
- super().__init__("DiscoverUM3Action", catalog.i18nc("@action","Connect via Network"))
- self._qml_url = "resources/qml/DiscoverUM3Action.qml"
-
- self._network_plugin = None #type: Optional[UM3OutputDevicePlugin]
-
- self.__additional_components_view = None #type: Optional[QObject]
-
- CuraApplication.getInstance().engineCreatedSignal.connect(self._createAdditionalComponentsView)
-
- self._last_zero_conf_event_time = time.time() #type: float
-
- # Time to wait after a zero-conf service change before allowing a zeroconf reset
- self._zero_conf_change_grace_period = 0.25 #type: float
-
- @pyqtSlot()
- def startDiscovery(self):
- if not self._network_plugin:
- Logger.log("d", "Starting device discovery.")
- self._network_plugin = CuraApplication.getInstance().getOutputDeviceManager().getOutputDevicePlugin("UM3NetworkPrinting")
- self._network_plugin.discoveredDevicesChanged.connect(self._onDeviceDiscoveryChanged)
- self.discoveredDevicesChanged.emit()
-
- ## Re-filters the list of devices.
- @pyqtSlot()
- def reset(self):
- Logger.log("d", "Reset the list of found devices.")
- if self._network_plugin:
- self._network_plugin.resetLastManualDevice()
- self.discoveredDevicesChanged.emit()
-
- @pyqtSlot()
- def restartDiscovery(self):
- # Ensure that there is a bit of time after a printer has been discovered.
- # This is a work around for an issue with Qt 5.5.1 up to Qt 5.7 which can segfault if we do this too often.
- # It's most likely that the QML engine is still creating delegates, where the python side already deleted or
- # garbage collected the data.
- # Whatever the case, waiting a bit ensures that it doesn't crash.
- if time.time() - self._last_zero_conf_event_time > self._zero_conf_change_grace_period:
- if not self._network_plugin:
- self.startDiscovery()
- else:
- self._network_plugin.startDiscovery()
-
- @pyqtSlot(str, str)
- def removeManualDevice(self, key, address):
- if not self._network_plugin:
- return
-
- self._network_plugin.removeManualDevice(key, address)
-
- @pyqtSlot(str, str)
- def setManualDevice(self, key, address):
- if key != "":
- # This manual printer replaces a current manual printer
- self._network_plugin.removeManualDevice(key)
-
- if address != "":
- self._network_plugin.addManualDevice(address)
-
- def _onDeviceDiscoveryChanged(self, *args):
- self._last_zero_conf_event_time = time.time()
- self.discoveredDevicesChanged.emit()
-
- @pyqtProperty("QVariantList", notify = discoveredDevicesChanged)
- def foundDevices(self):
- if self._network_plugin:
-
- printers = list(self._network_plugin.getDiscoveredDevices().values())
- printers.sort(key = lambda k: k.name)
- return printers
- else:
- return []
-
- @pyqtSlot(str)
- def setGroupName(self, group_name: str) -> None:
- Logger.log("d", "Attempting to set the group name of the active machine to %s", group_name)
- global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
- if global_container_stack:
- meta_data = global_container_stack.getMetaData()
- if "group_name" in meta_data:
- previous_connect_group_name = meta_data["group_name"]
- global_container_stack.setMetaDataEntry("group_name", group_name)
- # Find all the places where there is the same group name and change it accordingly
- CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "group_name", value = previous_connect_group_name, new_value = group_name)
- else:
- global_container_stack.setMetaDataEntry("group_name", group_name)
- # Set the default value for "hidden", which is used when you have a group with multiple types of printers
- global_container_stack.setMetaDataEntry("hidden", False)
-
- if self._network_plugin:
- # Ensure that the connection states are refreshed.
- self._network_plugin.reCheckConnections()
-
- # Associates the currently active machine with the given printer device. The network connection information will be
- # stored into the metadata of the currently active machine.
- @pyqtSlot(QObject)
- def associateActiveMachineWithPrinterDevice(self, printer_device: Optional["PrinterOutputDevice"]) -> None:
- if not printer_device:
- return
-
- Logger.log("d", "Attempting to set the network key of the active machine to %s", printer_device.key)
-
- global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
- if not global_container_stack:
- return
-
- meta_data = global_container_stack.getMetaData()
-
- if "um_network_key" in meta_data: # Global stack already had a connection, but it's changed.
- old_network_key = meta_data["um_network_key"]
- # Since we might have a bunch of hidden stacks, we also need to change it there.
- metadata_filter = {"um_network_key": old_network_key}
- containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine", **metadata_filter)
-
- for container in containers:
- container.setMetaDataEntry("um_network_key", printer_device.key)
-
- # Delete old authentication data.
- Logger.log("d", "Removing old authentication id %s for device %s",
- global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key)
-
- container.removeMetaDataEntry("network_authentication_id")
- container.removeMetaDataEntry("network_authentication_key")
-
- # Ensure that these containers do know that they are configured for network connection
- container.addConfiguredConnectionType(printer_device.connectionType.value)
-
- else: # Global stack didn't have a connection yet, configure it.
- global_container_stack.setMetaDataEntry("um_network_key", printer_device.key)
- global_container_stack.addConfiguredConnectionType(printer_device.connectionType.value)
-
- if self._network_plugin:
- # Ensure that the connection states are refreshed.
- self._network_plugin.reCheckConnections()
-
- @pyqtSlot(result = str)
- def getStoredKey(self) -> str:
- global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
- if global_container_stack:
- meta_data = global_container_stack.getMetaData()
- if "um_network_key" in meta_data:
- return global_container_stack.getMetaDataEntry("um_network_key")
-
- return ""
-
- @pyqtSlot(result = str)
- def getLastManualEntryKey(self) -> str:
- if self._network_plugin:
- return self._network_plugin.getLastManualDevice()
- return ""
-
- @pyqtSlot(str, result = bool)
- def existsKey(self, key: str) -> bool:
- return CuraApplication.getInstance().getMachineManager().existNetworkInstances(network_key = key)
-
- @pyqtSlot()
- def loadConfigurationFromPrinter(self) -> None:
- machine_manager = CuraApplication.getInstance().getMachineManager()
- hotend_ids = machine_manager.printerOutputDevices[0].hotendIds
- for index in range(len(hotend_ids)):
- machine_manager.printerOutputDevices[0].hotendIdChanged.emit(index, hotend_ids[index])
- material_ids = machine_manager.printerOutputDevices[0].materialIds
- for index in range(len(material_ids)):
- machine_manager.printerOutputDevices[0].materialIdChanged.emit(index, material_ids[index])
-
- def _createAdditionalComponentsView(self) -> None:
- Logger.log("d", "Creating additional ui components for UM3.")
-
- # Create networking dialog
- plugin_path = PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")
- if not plugin_path:
- return
- path = os.path.join(plugin_path, "resources/qml/UM3InfoComponents.qml")
- self.__additional_components_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
- if not self.__additional_components_view:
- Logger.log("w", "Could not create ui components for UM3.")
- return
-
- # Create extra components
- CuraApplication.getInstance().addAdditionalComponent("monitorButtons", self.__additional_components_view.findChild(QObject, "networkPrinterConnectButton"))
diff --git a/plugins/UM3NetworkPrinting/src/ExportFileJob.py b/plugins/UM3NetworkPrinting/src/ExportFileJob.py
new file mode 100644
index 0000000000..56d15bc835
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/ExportFileJob.py
@@ -0,0 +1,39 @@
+from typing import List, Optional
+
+from UM.FileHandler.FileHandler import FileHandler
+from UM.FileHandler.WriteFileJob import WriteFileJob
+from UM.Logger import Logger
+from UM.Scene.SceneNode import SceneNode
+from cura.CuraApplication import CuraApplication
+
+from .MeshFormatHandler import MeshFormatHandler
+
+
+## Job that exports the build plate to the correct file format for the target cluster.
+class ExportFileJob(WriteFileJob):
+
+ def __init__(self, file_handler: Optional[FileHandler], nodes: List[SceneNode], firmware_version: str) -> None:
+
+ self._mesh_format_handler = MeshFormatHandler(file_handler, firmware_version)
+ if not self._mesh_format_handler.is_valid:
+ Logger.log("e", "Missing file or mesh writer!")
+ return
+
+ super().__init__(self._mesh_format_handler.writer, self._mesh_format_handler.createStream(), nodes,
+ self._mesh_format_handler.file_mode)
+
+ # Determine the filename.
+ job_name = CuraApplication.getInstance().getPrintInformation().jobName
+ extension = self._mesh_format_handler.preferred_format.get("extension", "")
+ self.setFileName("{}.{}".format(job_name, extension))
+
+ ## Get the mime type of the selected export file type.
+ def getMimeType(self) -> str:
+ return self._mesh_format_handler.mime_type
+
+ ## Get the job result as bytes as that is what we need to upload to the cluster.
+ def getOutput(self) -> bytes:
+ output = self.getStream().getvalue()
+ if isinstance(output, str):
+ output = output.encode("utf-8")
+ return output
diff --git a/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py
deleted file mode 100644
index 2c7c33d382..0000000000
--- a/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py
+++ /dev/null
@@ -1,644 +0,0 @@
-from typing import List, Optional
-
-from cura.CuraApplication import CuraApplication
-from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice, AuthState
-from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
-from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
-from cura.PrinterOutputDevice import ConnectionType
-
-from cura.Settings.ContainerManager import ContainerManager
-from cura.Settings.ExtruderManager import ExtruderManager
-
-from UM.FileHandler.FileHandler import FileHandler
-from UM.i18n import i18nCatalog
-from UM.Logger import Logger
-from UM.Message import Message
-from UM.PluginRegistry import PluginRegistry
-from UM.Scene.SceneNode import SceneNode
-from UM.Settings.ContainerRegistry import ContainerRegistry
-
-from PyQt5.QtNetwork import QNetworkRequest
-from PyQt5.QtCore import QTimer, QUrl
-from PyQt5.QtWidgets import QMessageBox
-
-from .LegacyUM3PrinterOutputController import LegacyUM3PrinterOutputController
-
-from time import time
-
-import json
-import os
-
-
-i18n_catalog = i18nCatalog("cura")
-
-
-## This is the output device for the "Legacy" API of the UM3. All firmware before 4.0.1 uses this API.
-# Everything after that firmware uses the ClusterUM3Output.
-# The Legacy output device can only have one printer (whereas the cluster can have 0 to n).
-#
-# Authentication is done in a number of steps;
-# 1. Request an id / key pair by sending the application & user name. (state = authRequested)
-# 2. Machine sends this back and will display an approve / deny message on screen. (state = AuthReceived)
-# 3. OutputDevice will poll if the button was pressed.
-# 4. At this point the machine either has the state Authenticated or AuthenticationDenied.
-# 5. As a final step, we verify the authentication, as this forces the QT manager to setup the authenticator.
-class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
- def __init__(self, device_id, address: str, properties, parent = None) -> None:
- super().__init__(device_id = device_id, address = address, properties = properties, connection_type = ConnectionType.NetworkConnection, parent = parent)
- self._api_prefix = "/api/v1/"
- self._number_of_extruders = 2
-
- self._authentication_id = None
- self._authentication_key = None
-
- self._authentication_counter = 0
- self._max_authentication_counter = 5 * 60 # Number of attempts before authentication timed out (5 min)
-
- self._authentication_timer = QTimer()
- self._authentication_timer.setInterval(1000) # TODO; Add preference for update interval
- self._authentication_timer.setSingleShot(False)
-
- self._authentication_timer.timeout.connect(self._onAuthenticationTimer)
-
- # The messages are created when connect is called the first time.
- # This ensures that the messages are only created for devices that actually want to connect.
- self._authentication_requested_message = None
- self._authentication_failed_message = None
- self._authentication_succeeded_message = None
- self._not_authenticated_message = None
-
- self.authenticationStateChanged.connect(self._onAuthenticationStateChanged)
-
- self.setPriority(3) # Make sure the output device gets selected above local file output
- self.setName(self._id)
- self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
- self.setDescription(i18n_catalog.i18nc("@properties:tooltip", "Print over network"))
-
- self.setIconName("print")
-
- if PluginRegistry.getInstance() is not None:
- self._monitor_view_qml_path = os.path.join(
- PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
- "resources", "qml", "MonitorStage.qml"
- )
-
- self._output_controller = LegacyUM3PrinterOutputController(self)
-
- def _onAuthenticationStateChanged(self):
- # We only accept commands if we are authenticated.
- self._setAcceptsCommands(self._authentication_state == AuthState.Authenticated)
-
- if self._authentication_state == AuthState.Authenticated:
- self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network."))
- elif self._authentication_state == AuthState.AuthenticationRequested:
- self.setConnectionText(i18n_catalog.i18nc("@info:status",
- "Connected over the network. Please approve the access request on the printer."))
- elif self._authentication_state == AuthState.AuthenticationDenied:
- self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network. No access to control the printer."))
-
-
- def _setupMessages(self):
- self._authentication_requested_message = Message(i18n_catalog.i18nc("@info:status",
- "Access to the printer requested. Please approve the request on the printer"),
- lifetime=0, dismissable=False, progress=0,
- title=i18n_catalog.i18nc("@info:title",
- "Authentication status"))
-
- self._authentication_failed_message = Message("", title=i18n_catalog.i18nc("@info:title", "Authentication Status"))
- self._authentication_failed_message.addAction("Retry", i18n_catalog.i18nc("@action:button", "Retry"), None,
- i18n_catalog.i18nc("@info:tooltip", "Re-send the access request"))
- self._authentication_failed_message.actionTriggered.connect(self._messageCallback)
- self._authentication_succeeded_message = Message(
- i18n_catalog.i18nc("@info:status", "Access to the printer accepted"),
- title=i18n_catalog.i18nc("@info:title", "Authentication Status"))
-
- self._not_authenticated_message = Message(
- i18n_catalog.i18nc("@info:status", "No access to print with this printer. Unable to send print job."),
- title=i18n_catalog.i18nc("@info:title", "Authentication Status"))
- self._not_authenticated_message.addAction("Request", i18n_catalog.i18nc("@action:button", "Request Access"),
- None, i18n_catalog.i18nc("@info:tooltip",
- "Send access request to the printer"))
- self._not_authenticated_message.actionTriggered.connect(self._messageCallback)
-
- def _messageCallback(self, message_id=None, action_id="Retry"):
- if action_id == "Request" or action_id == "Retry":
- if self._authentication_failed_message:
- self._authentication_failed_message.hide()
- if self._not_authenticated_message:
- self._not_authenticated_message.hide()
-
- self._requestAuthentication()
-
- def connect(self):
- super().connect()
- self._setupMessages()
- global_container = CuraApplication.getInstance().getGlobalContainerStack()
- if global_container:
- self._authentication_id = global_container.getMetaDataEntry("network_authentication_id", None)
- self._authentication_key = global_container.getMetaDataEntry("network_authentication_key", None)
-
- def close(self):
- super().close()
- if self._authentication_requested_message:
- self._authentication_requested_message.hide()
- if self._authentication_failed_message:
- self._authentication_failed_message.hide()
- if self._authentication_succeeded_message:
- self._authentication_succeeded_message.hide()
- self._sending_gcode = False
- self._compressing_gcode = False
- self._authentication_timer.stop()
-
- ## Send all material profiles to the printer.
- def _sendMaterialProfiles(self):
- Logger.log("i", "Sending material profiles to printer")
-
- # TODO: Might want to move this to a job...
- for container in ContainerRegistry.getInstance().findInstanceContainers(type="material"):
- try:
- xml_data = container.serialize()
- if xml_data == "" or xml_data is None:
- continue
-
- names = ContainerManager.getInstance().getLinkedMaterials(container.getId())
- if names:
- # There are other materials that share this GUID.
- if not container.isReadOnly():
- continue # If it's not readonly, it's created by user, so skip it.
-
- file_name = "none.xml"
-
- self.postForm("materials", "form-data; name=\"file\";filename=\"%s\"" % file_name, xml_data.encode(), on_finished=None)
-
- except NotImplementedError:
- # If the material container is not the most "generic" one it can't be serialized an will raise a
- # NotImplementedError. We can simply ignore these.
- pass
-
- def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False, file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
- if not self.activePrinter:
- # No active printer. Unable to write
- return
-
- if self.activePrinter.state not in ["idle", ""]:
- # Printer is not able to accept commands.
- return
-
- if self._authentication_state != AuthState.Authenticated:
- # Not authenticated, so unable to send job.
- return
-
- self.writeStarted.emit(self)
-
- gcode_dict = getattr(CuraApplication.getInstance().getController().getScene(), "gcode_dict", [])
- active_build_plate_id = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
- gcode_list = gcode_dict[active_build_plate_id]
-
- if not gcode_list:
- # Unable to find g-code. Nothing to send
- return
-
- self._gcode = gcode_list
-
- errors = self._checkForErrors()
- if errors:
- text = i18n_catalog.i18nc("@label", "Unable to start a new print job.")
- informative_text = i18n_catalog.i18nc("@label",
- "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. "
- "Please resolve this issues before continuing.")
- detailed_text = ""
- for error in errors:
- detailed_text += error + "\n"
-
- CuraApplication.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Mismatched configuration"),
- text,
- informative_text,
- detailed_text,
- buttons=QMessageBox.Ok,
- icon=QMessageBox.Critical,
- callback = self._messageBoxCallback
- )
- return # Don't continue; Errors must block sending the job to the printer.
-
- # There might be multiple things wrong with the configuration. Check these before starting.
- warnings = self._checkForWarnings()
-
- if warnings:
- text = i18n_catalog.i18nc("@label", "Are you sure you wish to print with the selected configuration?")
- informative_text = i18n_catalog.i18nc("@label",
- "There is a mismatch between the configuration or calibration of the printer and Cura. "
- "For the best result, always slice for the PrintCores and materials that are inserted in your printer.")
- detailed_text = ""
- for warning in warnings:
- detailed_text += warning + "\n"
-
- CuraApplication.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Mismatched configuration"),
- text,
- informative_text,
- detailed_text,
- buttons=QMessageBox.Yes + QMessageBox.No,
- icon=QMessageBox.Question,
- callback=self._messageBoxCallback
- )
- return
-
- # No warnings or errors, so we're good to go.
- self._startPrint()
-
- # Notify the UI that a switch to the print monitor should happen
- CuraApplication.getInstance().getController().setActiveStage("MonitorStage")
-
- def _startPrint(self):
- Logger.log("i", "Sending print job to printer.")
- if self._sending_gcode:
- self._error_message = Message(
- i18n_catalog.i18nc("@info:status",
- "Sending new jobs (temporarily) blocked, still sending the previous print job."))
- self._error_message.show()
- return
-
- self._sending_gcode = True
-
- self._send_gcode_start = time()
- self._progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), 0, False, -1,
- i18n_catalog.i18nc("@info:title", "Sending Data"))
- self._progress_message.addAction("Abort", i18n_catalog.i18nc("@action:button", "Cancel"), None, "")
- self._progress_message.actionTriggered.connect(self._progressMessageActionTriggered)
- self._progress_message.show()
-
- compressed_gcode = self._compressGCode()
- if compressed_gcode is None:
- # Abort was called.
- return
-
- file_name = "%s.gcode.gz" % CuraApplication.getInstance().getPrintInformation().jobName
- self.postForm("print_job", "form-data; name=\"file\";filename=\"%s\"" % file_name, compressed_gcode,
- on_finished=self._onPostPrintJobFinished)
-
- return
-
- def _progressMessageActionTriggered(self, message_id=None, action_id=None):
- if action_id == "Abort":
- Logger.log("d", "User aborted sending print to remote.")
- self._progress_message.hide()
- self._compressing_gcode = False
- self._sending_gcode = False
- CuraApplication.getInstance().getController().setActiveStage("PrepareStage")
-
- def _onPostPrintJobFinished(self, reply):
- self._progress_message.hide()
- self._sending_gcode = False
-
- def _onUploadPrintJobProgress(self, bytes_sent, bytes_total):
- if bytes_total > 0:
- new_progress = bytes_sent / bytes_total * 100
- # Treat upload progress as response. Uploading can take more than 10 seconds, so if we don't, we can get
- # timeout responses if this happens.
- self._last_response_time = time()
- if new_progress > self._progress_message.getProgress():
- self._progress_message.show() # Ensure that the message is visible.
- self._progress_message.setProgress(bytes_sent / bytes_total * 100)
- else:
- self._progress_message.setProgress(0)
-
- self._progress_message.hide()
-
- def _messageBoxCallback(self, button):
- def delayedCallback():
- if button == QMessageBox.Yes:
- self._startPrint()
- else:
- CuraApplication.getInstance().getController().setActiveStage("PrepareStage")
- # For some unknown reason Cura on OSX will hang if we do the call back code
- # immediately without first returning and leaving QML's event system.
-
- QTimer.singleShot(100, delayedCallback)
-
- def _checkForErrors(self):
- errors = []
- print_information = CuraApplication.getInstance().getPrintInformation()
- if not print_information.materialLengths:
- Logger.log("w", "There is no material length information. Unable to check for errors.")
- return errors
-
- for index, extruder in enumerate(self.activePrinter.extruders):
- # Due to airflow issues, both slots must be loaded, regardless if they are actually used or not.
- if extruder.hotendID == "":
- # No Printcore loaded.
- errors.append(i18n_catalog.i18nc("@info:status", "No Printcore loaded in slot {slot_number}".format(slot_number=index + 1)))
-
- if index < len(print_information.materialLengths) and print_information.materialLengths[index] != 0:
- # The extruder is by this print.
- if extruder.activeMaterial is None:
- # No active material
- errors.append(i18n_catalog.i18nc("@info:status", "No material loaded in slot {slot_number}".format(slot_number=index + 1)))
- return errors
-
- def _checkForWarnings(self):
- warnings = []
- print_information = CuraApplication.getInstance().getPrintInformation()
-
- if not print_information.materialLengths:
- Logger.log("w", "There is no material length information. Unable to check for warnings.")
- return warnings
-
- extruder_manager = ExtruderManager.getInstance()
-
- for index, extruder in enumerate(self.activePrinter.extruders):
- if index < len(print_information.materialLengths) and print_information.materialLengths[index] != 0:
- # The extruder is by this print.
-
- # TODO: material length check
-
- # Check if the right Printcore is active.
- variant = extruder_manager.getExtruderStack(index).findContainer({"type": "variant"})
- if variant:
- if variant.getName() != extruder.hotendID:
- warnings.append(i18n_catalog.i18nc("@label", "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}".format(cura_printcore_name = variant.getName(), remote_printcore_name = extruder.hotendID, extruder_id = index + 1)))
- else:
- Logger.log("w", "Unable to find variant.")
-
- # Check if the right material is loaded.
- local_material = extruder_manager.getExtruderStack(index).findContainer({"type": "material"})
- if local_material:
- if extruder.activeMaterial.guid != local_material.getMetaDataEntry("GUID"):
- Logger.log("w", "Extruder %s has a different material (%s) as Cura (%s)", index + 1, extruder.activeMaterial.guid, local_material.getMetaDataEntry("GUID"))
- warnings.append(i18n_catalog.i18nc("@label", "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}").format(local_material.getName(), extruder.activeMaterial.name, index + 1))
- else:
- Logger.log("w", "Unable to find material.")
-
- return warnings
-
- def _update(self):
- if not super()._update():
- return
- if self._authentication_state == AuthState.NotAuthenticated:
- if self._authentication_id is None and self._authentication_key is None:
- # This machine doesn't have any authentication, so request it.
- self._requestAuthentication()
- elif self._authentication_id is not None and self._authentication_key is not None:
- # We have authentication info, but we haven't checked it out yet. Do so now.
- self._verifyAuthentication()
- elif self._authentication_state == AuthState.AuthenticationReceived:
- # We have an authentication, but it's not confirmed yet.
- self._checkAuthentication()
-
- # We don't need authentication for requesting info, so we can go right ahead with requesting this.
- self.get("printer", on_finished=self._onGetPrinterDataFinished)
- self.get("print_job", on_finished=self._onGetPrintJobFinished)
-
- def _resetAuthenticationRequestedMessage(self):
- if self._authentication_requested_message:
- self._authentication_requested_message.hide()
- self._authentication_timer.stop()
- self._authentication_counter = 0
-
- def _onAuthenticationTimer(self):
- self._authentication_counter += 1
- self._authentication_requested_message.setProgress(
- self._authentication_counter / self._max_authentication_counter * 100)
- if self._authentication_counter > self._max_authentication_counter:
- self._authentication_timer.stop()
- Logger.log("i", "Authentication timer ended. Setting authentication to denied for printer: %s" % self._id)
- self.setAuthenticationState(AuthState.AuthenticationDenied)
- self._resetAuthenticationRequestedMessage()
- self._authentication_failed_message.show()
-
- def _verifyAuthentication(self):
- Logger.log("d", "Attempting to verify authentication")
- # This will ensure that the "_onAuthenticationRequired" is triggered, which will setup the authenticator.
- self.get("auth/verify", on_finished=self._onVerifyAuthenticationCompleted)
-
- def _onVerifyAuthenticationCompleted(self, reply):
- status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
- if status_code == 401:
- # Something went wrong; We somehow tried to verify authentication without having one.
- Logger.log("d", "Attempted to verify auth without having one.")
- self._authentication_id = None
- self._authentication_key = None
- self.setAuthenticationState(AuthState.NotAuthenticated)
- elif status_code == 403 and self._authentication_state != AuthState.Authenticated:
- # If we were already authenticated, we probably got an older message back all of the sudden. Drop that.
- Logger.log("d",
- "While trying to verify the authentication state, we got a forbidden response. Our own auth state was %s. ",
- self._authentication_state)
- self.setAuthenticationState(AuthState.AuthenticationDenied)
- self._authentication_failed_message.show()
- elif status_code == 200:
- self.setAuthenticationState(AuthState.Authenticated)
-
- def _checkAuthentication(self):
- Logger.log("d", "Checking if authentication is correct for id %s and key %s", self._authentication_id, self._getSafeAuthKey())
- self.get("auth/check/" + str(self._authentication_id), on_finished=self._onCheckAuthenticationFinished)
-
- def _onCheckAuthenticationFinished(self, reply):
- if str(self._authentication_id) not in reply.url().toString():
- Logger.log("w", "Got an old id response.")
- # Got response for old authentication ID.
- return
- try:
- data = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except json.decoder.JSONDecodeError:
- Logger.log("w", "Received an invalid authentication check from printer: Not valid JSON.")
- return
-
- if data.get("message", "") == "authorized":
- Logger.log("i", "Authentication was approved")
- self.setAuthenticationState(AuthState.Authenticated)
- self._saveAuthentication()
-
- # Double check that everything went well.
- self._verifyAuthentication()
-
- # Notify the user.
- self._resetAuthenticationRequestedMessage()
- self._authentication_succeeded_message.show()
- elif data.get("message", "") == "unauthorized":
- Logger.log("i", "Authentication was denied.")
- self.setAuthenticationState(AuthState.AuthenticationDenied)
- self._authentication_failed_message.show()
-
- def _saveAuthentication(self) -> None:
- global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
- if self._authentication_key is None:
- Logger.log("e", "Authentication key is None, nothing to save.")
- return
- if self._authentication_id is None:
- Logger.log("e", "Authentication id is None, nothing to save.")
- return
- if global_container_stack:
- global_container_stack.setMetaDataEntry("network_authentication_key", self._authentication_key)
-
- global_container_stack.setMetaDataEntry("network_authentication_id", self._authentication_id)
-
- # Force save so we are sure the data is not lost.
- CuraApplication.getInstance().saveStack(global_container_stack)
- Logger.log("i", "Authentication succeeded for id %s and key %s", self._authentication_id,
- self._getSafeAuthKey())
- else:
- Logger.log("e", "Unable to save authentication for id %s and key %s", self._authentication_id,
- self._getSafeAuthKey())
-
- def _onRequestAuthenticationFinished(self, reply):
- try:
- data = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except json.decoder.JSONDecodeError:
- Logger.log("w", "Received an invalid authentication request reply from printer: Not valid JSON.")
- self.setAuthenticationState(AuthState.NotAuthenticated)
- return
-
- self.setAuthenticationState(AuthState.AuthenticationReceived)
- self._authentication_id = data["id"]
- self._authentication_key = data["key"]
- Logger.log("i", "Got a new authentication ID (%s) and KEY (%s). Waiting for authorization.",
- self._authentication_id, self._getSafeAuthKey())
-
- def _requestAuthentication(self):
- self._authentication_requested_message.show()
- self._authentication_timer.start()
-
- # Reset any previous authentication info. If this isn't done, the "Retry" action on the failed message might
- # give issues.
- self._authentication_key = None
- self._authentication_id = None
-
- self.post("auth/request",
- json.dumps({"application": "Cura-" + CuraApplication.getInstance().getVersion(),
- "user": self._getUserName()}),
- on_finished=self._onRequestAuthenticationFinished)
-
- self.setAuthenticationState(AuthState.AuthenticationRequested)
-
- def _onAuthenticationRequired(self, reply, authenticator):
- if self._authentication_id is not None and self._authentication_key is not None:
- Logger.log("d",
- "Authentication was required for printer: %s. Setting up authenticator with ID %s and key %s",
- self._id, self._authentication_id, self._getSafeAuthKey())
- authenticator.setUser(self._authentication_id)
- authenticator.setPassword(self._authentication_key)
- else:
- Logger.log("d", "No authentication is available to use for %s, but we did got a request for it.", self._id)
-
- def _onGetPrintJobFinished(self, reply):
- status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
-
- if not self._printers:
- return # Ignore the data for now, we don't have info about a printer yet.
- printer = self._printers[0]
-
- if status_code == 200:
- try:
- result = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except json.decoder.JSONDecodeError:
- Logger.log("w", "Received an invalid print job state message: Not valid JSON.")
- return
- if printer.activePrintJob is None:
- print_job = PrintJobOutputModel(output_controller=self._output_controller)
- printer.updateActivePrintJob(print_job)
- else:
- print_job = printer.activePrintJob
- print_job.updateState(result["state"])
- print_job.updateTimeElapsed(result["time_elapsed"])
- print_job.updateTimeTotal(result["time_total"])
- print_job.updateName(result["name"])
- elif status_code == 404:
- # No job found, so delete the active print job (if any!)
- printer.updateActivePrintJob(None)
- else:
- Logger.log("w",
- "Got status code {status_code} while trying to get printer data".format(status_code=status_code))
-
- def materialHotendChangedMessage(self, callback):
- CuraApplication.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Sync with your printer"),
- i18n_catalog.i18nc("@label",
- "Would you like to use your current printer configuration in Cura?"),
- i18n_catalog.i18nc("@label",
- "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."),
- buttons=QMessageBox.Yes + QMessageBox.No,
- icon=QMessageBox.Question,
- callback=callback
- )
-
- def _onGetPrinterDataFinished(self, reply):
- status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
- if status_code == 200:
- try:
- result = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except json.decoder.JSONDecodeError:
- Logger.log("w", "Received an invalid printer state message: Not valid JSON.")
- return
-
- if not self._printers:
- # Quickest way to get the firmware version is to grab it from the zeroconf.
- firmware_version = self._properties.get(b"firmware_version", b"").decode("utf-8")
- self._printers = [PrinterOutputModel(output_controller=self._output_controller, number_of_extruders=self._number_of_extruders, firmware_version=firmware_version)]
- self._printers[0].setCameraUrl(QUrl("http://" + self._address + ":8080/?action=stream"))
- for extruder in self._printers[0].extruders:
- extruder.activeMaterialChanged.connect(self.materialIdChanged)
- extruder.hotendIDChanged.connect(self.hotendIdChanged)
- self.printersChanged.emit()
-
- # LegacyUM3 always has a single printer.
- printer = self._printers[0]
- printer.updateBedTemperature(result["bed"]["temperature"]["current"])
- printer.updateTargetBedTemperature(result["bed"]["temperature"]["target"])
- printer.updateState(result["status"])
-
- try:
- # If we're still handling the request, we should ignore remote for a bit.
- if not printer.getController().isPreheatRequestInProgress():
- printer.updateIsPreheating(result["bed"]["pre_heat"]["active"])
- except KeyError:
- # Older firmwares don't support preheating, so we need to fake it.
- pass
-
- head_position = result["heads"][0]["position"]
- printer.updateHeadPosition(head_position["x"], head_position["y"], head_position["z"])
-
- for index in range(0, self._number_of_extruders):
- temperatures = result["heads"][0]["extruders"][index]["hotend"]["temperature"]
- extruder = printer.extruders[index]
- extruder.updateTargetHotendTemperature(temperatures["target"])
- extruder.updateHotendTemperature(temperatures["current"])
-
- material_guid = result["heads"][0]["extruders"][index]["active_material"]["guid"]
-
- if extruder.activeMaterial is None or extruder.activeMaterial.guid != material_guid:
- # Find matching material (as we need to set brand, type & color)
- containers = ContainerRegistry.getInstance().findInstanceContainers(type="material",
- GUID=material_guid)
- if containers:
- color = containers[0].getMetaDataEntry("color_code")
- brand = containers[0].getMetaDataEntry("brand")
- material_type = containers[0].getMetaDataEntry("material")
- name = containers[0].getName()
- else:
- # Unknown material.
- color = "#00000000"
- brand = "Unknown"
- material_type = "Unknown"
- name = "Unknown"
- material = MaterialOutputModel(guid=material_guid, type=material_type,
- brand=brand, color=color, name = name)
- extruder.updateActiveMaterial(material)
-
- try:
- hotend_id = result["heads"][0]["extruders"][index]["hotend"]["id"]
- except KeyError:
- hotend_id = ""
- printer.extruders[index].updateHotendID(hotend_id)
-
- else:
- Logger.log("w",
- "Got status code {status_code} while trying to get printer data".format(status_code = status_code))
-
- ## Convenience function to "blur" out all but the last 5 characters of the auth key.
- # This can be used to debug print the key, without it compromising the security.
- def _getSafeAuthKey(self):
- if self._authentication_key is not None:
- result = self._authentication_key[-5:]
- result = "********" + result
- return result
-
- return self._authentication_key
diff --git a/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.py b/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.py
deleted file mode 100644
index 63167b4ffb..0000000000
--- a/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright (c) 2019 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
-from PyQt5.QtCore import QTimer
-from UM.Version import Version
-
-MYPY = False
-if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-
-
-class LegacyUM3PrinterOutputController(PrinterOutputController):
- def __init__(self, output_device):
- super().__init__(output_device)
- self._preheat_bed_timer = QTimer()
- self._preheat_bed_timer.setSingleShot(True)
- self._preheat_bed_timer.timeout.connect(self._onPreheatBedTimerFinished)
- self._preheat_printer = None
-
- self.can_control_manually = False
- self.can_send_raw_gcode = False
-
- # Are we still waiting for a response about preheat?
- # We need this so we can already update buttons, so it feels more snappy.
- self._preheat_request_in_progress = False
-
- def isPreheatRequestInProgress(self):
- return self._preheat_request_in_progress
-
- def setJobState(self, job: "PrintJobOutputModel", state: str):
- data = "{\"target\": \"%s\"}" % state
- self._output_device.put("print_job/state", data, on_finished=None)
-
- def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float):
- data = str(temperature)
- self._output_device.put("printer/bed/temperature/target", data, on_finished = self._onPutBedTemperatureCompleted)
-
- def _onPutBedTemperatureCompleted(self, reply):
- if Version(self._preheat_printer.firmwareVersion) < Version("3.5.92"):
- # If it was handling a preheat, it isn't anymore.
- self._preheat_request_in_progress = False
-
- def _onPutPreheatBedCompleted(self, reply):
- self._preheat_request_in_progress = False
-
- def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed):
- head_pos = printer._head_position
- new_x = head_pos.x + x
- new_y = head_pos.y + y
- new_z = head_pos.z + z
- data = "{\n\"x\":%s,\n\"y\":%s,\n\"z\":%s\n}" %(new_x, new_y, new_z)
- self._output_device.put("printer/heads/0/position", data, on_finished=None)
-
- def homeBed(self, printer):
- self._output_device.put("printer/heads/0/position/z", "0", on_finished=None)
-
- def _onPreheatBedTimerFinished(self):
- self.setTargetBedTemperature(self._preheat_printer, 0)
- self._preheat_printer.updateIsPreheating(False)
- self._preheat_request_in_progress = True
-
- def cancelPreheatBed(self, printer: "PrinterOutputModel"):
- self.preheatBed(printer, temperature=0, duration=0)
- self._preheat_bed_timer.stop()
- printer.updateIsPreheating(False)
-
- def preheatBed(self, printer: "PrinterOutputModel", temperature, duration):
- try:
- temperature = round(temperature) # The API doesn't allow floating point.
- duration = round(duration)
- except ValueError:
- return # Got invalid values, can't pre-heat.
-
- if duration > 0:
- data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration)
- else:
- data = """{"temperature": "%i"}""" % temperature
-
- # Real bed pre-heating support is implemented from 3.5.92 and up.
-
- if Version(printer.firmwareVersion) < Version("3.5.92"):
- # No firmware-side duration support then, so just set target bed temp and set a timer.
- self.setTargetBedTemperature(printer, temperature=temperature)
- self._preheat_bed_timer.setInterval(duration * 1000)
- self._preheat_bed_timer.start()
- self._preheat_printer = printer
- printer.updateIsPreheating(True)
- return
-
- self._output_device.put("printer/bed/pre_heat", data, on_finished = self._onPutPreheatBedCompleted)
- printer.updateIsPreheating(True)
- self._preheat_request_in_progress = True
-
-
diff --git a/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py b/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py
index c3cd82a86d..9927bf744e 100644
--- a/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py
+++ b/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import io
from typing import Optional, Dict, Union, List, cast
@@ -32,7 +32,7 @@ class MeshFormatHandler:
# \return A dict with the file format details, with the following keys:
# {id: str, extension: str, description: str, mime_type: str, mode: int, hide_in_file_dialog: bool}
@property
- def preferred_format(self) -> Optional[Dict[str, Union[str, int, bool]]]:
+ def preferred_format(self) -> Dict[str, Union[str, int, bool]]:
return self._preferred_format
## Gets the file writer for the given file handler and mime type.
@@ -90,6 +90,7 @@ class MeshFormatHandler:
machine_file_formats = global_stack.getMetaDataEntry("file_formats").split(";")
machine_file_formats = [file_type.strip() for file_type in machine_file_formats]
+
# Exception for UM3 firmware version >=4.4: UFP is now supported and should be the preferred file format.
if "application/x-ufp" not in machine_file_formats and Version(firmware_version) >= Version("4.4"):
machine_file_formats = ["application/x-ufp"] + machine_file_formats
diff --git a/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py b/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py
new file mode 100644
index 0000000000..311356de8e
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import os
+
+from PyQt5.QtCore import QUrl
+from PyQt5.QtGui import QDesktopServices
+
+from UM import i18nCatalog
+from UM.Message import Message
+from cura.CuraApplication import CuraApplication
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+class CloudFlowMessage(Message):
+
+ def __init__(self, address: str) -> None:
+
+ image_path = os.path.join(
+ CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "",
+ "resources", "svg", "cloud-flow-start.svg"
+ )
+
+ super().__init__(
+ text=I18N_CATALOG.i18nc("@info:status",
+ "Send and monitor print jobs from anywhere using your Ultimaker account."),
+ lifetime=0,
+ dismissable=True,
+ option_state=False,
+ image_source=QUrl.fromLocalFile(image_path),
+ image_caption=I18N_CATALOG.i18nc("@info:status Ultimaker Cloud should not be translated.",
+ "Connect to Ultimaker Cloud"),
+ )
+ self._address = address
+ self.addAction("", I18N_CATALOG.i18nc("@action", "Get started"), "", "")
+ self.actionTriggered.connect(self._onCloudFlowStarted)
+
+ def _onCloudFlowStarted(self, messageId: str, actionId: str) -> None:
+ QDesktopServices.openUrl(QUrl("http://{}/cloud_connect".format(self._address)))
+ self.hide()
diff --git a/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py b/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py
new file mode 100644
index 0000000000..f4132dbcbc
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from UM import i18nCatalog
+from UM.Message import Message
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Message shown when trying to connect to a legacy printer device.
+class LegacyDeviceNoLongerSupportedMessage(Message):
+
+ # Singleton used to prevent duplicate messages of this type at the same time.
+ __is_visible = False
+
+ def __init__(self) -> None:
+ super().__init__(
+ text = I18N_CATALOG.i18nc("@info:status", "You are attempting to connect to a printer that is not "
+ "running Ultimaker Connect. Please update the printer to the "
+ "latest firmware."),
+ title = I18N_CATALOG.i18nc("@info:title", "Update your printer"),
+ lifetime = 10
+ )
+
+ def show(self) -> None:
+ if LegacyDeviceNoLongerSupportedMessage.__is_visible:
+ return
+ super().show()
+ LegacyDeviceNoLongerSupportedMessage.__is_visible = True
+
+ def hide(self, send_signal = True) -> None:
+ super().hide(send_signal)
+ LegacyDeviceNoLongerSupportedMessage.__is_visible = False
diff --git a/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py b/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py
new file mode 100644
index 0000000000..e021b2ae99
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import TYPE_CHECKING
+
+from UM import i18nCatalog
+from UM.Message import Message
+
+
+if TYPE_CHECKING:
+ from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Message shown when sending material files to cluster host.
+class MaterialSyncMessage(Message):
+
+ # Singleton used to prevent duplicate messages of this type at the same time.
+ __is_visible = False
+
+ def __init__(self, device: "UltimakerNetworkedPrinterOutputDevice") -> None:
+ super().__init__(
+ text = I18N_CATALOG.i18nc("@info:status", "Cura has detected material profiles that were not yet installed "
+ "on the host printer of group {0}.", device.name),
+ title = I18N_CATALOG.i18nc("@info:title", "Sending materials to printer"),
+ lifetime = 10,
+ dismissable = True
+ )
+
+ def show(self) -> None:
+ if MaterialSyncMessage.__is_visible:
+ return
+ super().show()
+ MaterialSyncMessage.__is_visible = True
+
+ def hide(self, send_signal = True) -> None:
+ super().hide(send_signal)
+ MaterialSyncMessage.__is_visible = False
diff --git a/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py b/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py
new file mode 100644
index 0000000000..77d7995fc7
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import TYPE_CHECKING
+
+from PyQt5.QtCore import QUrl
+from PyQt5.QtGui import QDesktopServices
+
+from UM import i18nCatalog
+from UM.Message import Message
+
+
+if TYPE_CHECKING:
+ from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Message shown when trying to connect to a printer that is not a host.
+class NotClusterHostMessage(Message):
+
+ # Singleton used to prevent duplicate messages of this type at the same time.
+ __is_visible = False
+
+ def __init__(self, device: "UltimakerNetworkedPrinterOutputDevice") -> None:
+ super().__init__(
+ text = I18N_CATALOG.i18nc("@info:status", "You are attempting to connect to {0} but it is not "
+ "the host of a group. You can visit the web page to configure "
+ "it as a group host.", device.name),
+ title = I18N_CATALOG.i18nc("@info:title", "Not a group host"),
+ lifetime = 0,
+ dismissable = True
+ )
+ self._address = device.address
+ self.addAction("", I18N_CATALOG.i18nc("@action", "Configure group"), "", "")
+ self.actionTriggered.connect(self._onConfigureClicked)
+
+ def show(self) -> None:
+ if NotClusterHostMessage.__is_visible:
+ return
+ super().show()
+ NotClusterHostMessage.__is_visible = True
+
+ def hide(self, send_signal = True) -> None:
+ super().hide(send_signal)
+ NotClusterHostMessage.__is_visible = False
+
+ def _onConfigureClicked(self, messageId: str, actionId: str) -> None:
+ QDesktopServices.openUrl(QUrl("http://{}/print_jobs".format(self._address)))
+ self.hide()
diff --git a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py
new file mode 100644
index 0000000000..be00292559
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from UM import i18nCatalog
+from UM.Message import Message
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Message shown when uploading a print job to a cluster is blocked because another upload is already in progress.
+class PrintJobUploadBlockedMessage(Message):
+
+ def __init__(self) -> None:
+ super().__init__(
+ text = I18N_CATALOG.i18nc("@info:status", "Please wait until the current job has been sent."),
+ title = I18N_CATALOG.i18nc("@info:title", "Print error"),
+ lifetime = 10
+ )
diff --git a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py
new file mode 100644
index 0000000000..bb26a84953
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from UM import i18nCatalog
+from UM.Message import Message
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Message shown when uploading a print job to a cluster failed.
+class PrintJobUploadErrorMessage(Message):
+
+ def __init__(self, message: str = None) -> None:
+ super().__init__(
+ text = message or I18N_CATALOG.i18nc("@info:text", "Could not upload the data to the printer."),
+ title = I18N_CATALOG.i18nc("@info:title", "Network error"),
+ lifetime = 10
+ )
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py
similarity index 82%
rename from plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py
rename to plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py
index d85f49c1a0..bdbab008e3 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py
+++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM import i18nCatalog
from UM.Message import Message
@@ -8,11 +8,11 @@ I18N_CATALOG = i18nCatalog("cura")
## Class responsible for showing a progress message while a mesh is being uploaded to the cloud.
-class CloudProgressMessage(Message):
+class PrintJobUploadProgressMessage(Message):
def __init__(self):
super().__init__(
- text = I18N_CATALOG.i18nc("@info:status", "Sending data to remote cluster"),
- title = I18N_CATALOG.i18nc("@info:status", "Sending data to remote cluster"),
+ title = I18N_CATALOG.i18nc("@info:status", "Sending Print Job"),
+ text = I18N_CATALOG.i18nc("@info:status", "Uploading print job to printer."),
progress = -1,
lifetime = 0,
dismissable = False,
diff --git a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py
new file mode 100644
index 0000000000..c9be28d57f
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from UM import i18nCatalog
+from UM.Message import Message
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Message shown when uploading a print job to a cluster succeeded.
+class PrintJobUploadSuccessMessage(Message):
+
+ def __init__(self) -> None:
+ super().__init__(
+ text = I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
+ title = I18N_CATALOG.i18nc("@info:title", "Data Sent"),
+ lifetime = 5
+ )
diff --git a/plugins/UM3NetworkPrinting/src/Messages/__init__.py b/plugins/UM3NetworkPrinting/src/Messages/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/UM3NetworkPrinting/src/Models.py b/plugins/UM3NetworkPrinting/src/Models.py
deleted file mode 100644
index c5b9b16665..0000000000
--- a/plugins/UM3NetworkPrinting/src/Models.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-
-## Base model that maps kwargs to instance attributes.
-class BaseModel:
- def __init__(self, **kwargs) -> None:
- self.__dict__.update(kwargs)
- self.validate()
-
- # Validates the model, raising an exception if the model is invalid.
- def validate(self) -> None:
- pass
-
-
-## Class representing a material that was fetched from the cluster API.
-class ClusterMaterial(BaseModel):
- def __init__(self, guid: str, version: int, **kwargs) -> None:
- self.guid = guid # type: str
- self.version = version # type: int
- super().__init__(**kwargs)
-
- def validate(self) -> None:
- if not self.guid:
- raise ValueError("guid is required on ClusterMaterial")
- if not self.version:
- raise ValueError("version is required on ClusterMaterial")
-
-
-## Class representing a local material that was fetched from the container registry.
-class LocalMaterial(BaseModel):
- def __init__(self, GUID: str, id: str, version: int, **kwargs) -> None:
- self.GUID = GUID # type: str
- self.id = id # type: str
- self.version = version # type: int
- super().__init__(**kwargs)
-
- #
- def validate(self) -> None:
- super().validate()
- if not self.GUID:
- raise ValueError("guid is required on LocalMaterial")
- if not self.version:
- raise ValueError("version is required on LocalMaterial")
- if not self.id:
- raise ValueError("id is required on LocalMaterial")
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/BaseCloudModel.py b/plugins/UM3NetworkPrinting/src/Models/BaseModel.py
similarity index 81%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/BaseCloudModel.py
rename to plugins/UM3NetworkPrinting/src/Models/BaseModel.py
index 18a8cb5cba..3d38a4b116 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/BaseCloudModel.py
+++ b/plugins/UM3NetworkPrinting/src/Models/BaseModel.py
@@ -1,13 +1,23 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from datetime import datetime, timezone
-from typing import Dict, Union, TypeVar, Type, List, Any
-
-from ...Models import BaseModel
+from typing import TypeVar, Dict, List, Any, Type, Union
-## Base class for the models used in the interface with the Ultimaker cloud APIs.
-class BaseCloudModel(BaseModel):
+# Type variable used in the parse methods below, which should be a subclass of BaseModel.
+T = TypeVar("T", bound="BaseModel")
+
+
+class BaseModel:
+
+ def __init__(self, **kwargs) -> None:
+ self.__dict__.update(kwargs)
+ self.validate()
+
+ # Validates the model, raising an exception if the model is invalid.
+ def validate(self) -> None:
+ pass
+
## Checks whether the two models are equal.
# \param other: The other model.
# \return True if they are equal, False if they are different.
@@ -24,9 +34,6 @@ class BaseCloudModel(BaseModel):
def toDict(self) -> Dict[str, Any]:
return self.__dict__
- # Type variable used in the parse methods below, which should be a subclass of BaseModel.
- T = TypeVar("T", bound=BaseModel)
-
## Parses a single model.
# \param model_class: The model class.
# \param values: The value of the model, which is usually a dictionary, but may also be already parsed.
diff --git a/plugins/UM3NetworkPrinting/src/ConfigurationChangeModel.py b/plugins/UM3NetworkPrinting/src/Models/ConfigurationChangeModel.py
similarity index 63%
rename from plugins/UM3NetworkPrinting/src/ConfigurationChangeModel.py
rename to plugins/UM3NetworkPrinting/src/Models/ConfigurationChangeModel.py
index ef8a212b76..58fae03679 100644
--- a/plugins/UM3NetworkPrinting/src/ConfigurationChangeModel.py
+++ b/plugins/UM3NetworkPrinting/src/Models/ConfigurationChangeModel.py
@@ -1,13 +1,18 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from PyQt5.QtCore import pyqtProperty, QObject
+
+
+BLOCKING_CHANGE_TYPES = [
+ "material_insert", "buildplate_change"
+]
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
class ConfigurationChangeModel(QObject):
def __init__(self, type_of_change: str, index: int, target_name: str, origin_name: str) -> None:
super().__init__()
- self._type_of_change = type_of_change
- # enum = ["material", "print_core_change"]
+ self._type_of_change = type_of_change # enum = ["material", "print_core_change"]
+ self._can_override = self._type_of_change not in BLOCKING_CHANGE_TYPES
self._index = index
self._target_name = target_name
self._origin_name = origin_name
@@ -27,3 +32,7 @@ class ConfigurationChangeModel(QObject):
@pyqtProperty(str, constant = True)
def originName(self) -> str:
return self._origin_name
+
+ @pyqtProperty(bool, constant = True)
+ def canOverride(self) -> bool:
+ return self._can_override
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py
similarity index 67%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py
index 9c0853e7c9..7ecfe8b0a3 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py
@@ -1,13 +1,13 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
## Class representing a cloud connected cluster.
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterResponse(BaseCloudModel):
+class CloudClusterResponse(BaseModel):
+
## Creates a new cluster response object.
# \param cluster_id: The secret unique ID, e.g. 'kBEeZWEifXbrXviO8mRYLx45P8k5lHVGs43XKvRniPg='.
# \param host_guid: The unique identifier of the print cluster host, e.g. 'e90ae0ac-1257-4403-91ee-a44c9b7e8050'.
@@ -15,14 +15,21 @@ class CloudClusterResponse(BaseCloudModel):
# \param is_online: Whether this cluster is currently connected to the cloud.
# \param status: The status of the cluster authentication (active or inactive).
# \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on.
+ # \param host_internal_ip: The internal IP address of the host printer.
+ # \param friendly_name: The human readable name of the host printer.
+ # \param printer_type: The machine type of the host printer.
def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str,
- host_version: Optional[str] = None, **kwargs) -> None:
+ host_internal_ip: Optional[str] = None, host_version: Optional[str] = None,
+ friendly_name: Optional[str] = None, printer_type: str = "ultimaker3", **kwargs) -> None:
self.cluster_id = cluster_id
self.host_guid = host_guid
self.host_name = host_name
self.status = status
self.is_online = is_online
self.host_version = host_version
+ self.host_internal_ip = host_internal_ip
+ self.friendly_name = friendly_name
+ self.printer_type = printer_type
super().__init__(**kwargs)
# Validates the model, raising an exception if the model is invalid.
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py
similarity index 52%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterStatus.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py
index b0250c2ebb..330e61d343 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterStatus.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py
@@ -1,26 +1,26 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from datetime import datetime
from typing import List, Dict, Union, Any
-from .CloudClusterPrinterStatus import CloudClusterPrinterStatus
-from .CloudClusterPrintJobStatus import CloudClusterPrintJobStatus
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
+from .ClusterPrinterStatus import ClusterPrinterStatus
+from .ClusterPrintJobStatus import ClusterPrintJobStatus
# Model that represents the status of the cluster for the cloud
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterStatus(BaseCloudModel):
+class CloudClusterStatus(BaseModel):
+
## Creates a new cluster status model object.
# \param printers: The latest status of each printer in the cluster.
# \param print_jobs: The latest status of each print job in the cluster.
# \param generated_time: The datetime when the object was generated on the server-side.
def __init__(self,
- printers: List[Union[CloudClusterPrinterStatus, Dict[str, Any]]],
- print_jobs: List[Union[CloudClusterPrintJobStatus, Dict[str, Any]]],
+ printers: List[Union[ClusterPrinterStatus, Dict[str, Any]]],
+ print_jobs: List[Union[ClusterPrintJobStatus, Dict[str, Any]]],
generated_time: Union[str, datetime],
**kwargs) -> None:
self.generated_time = self.parseDate(generated_time)
- self.printers = self.parseModels(CloudClusterPrinterStatus, printers)
- self.print_jobs = self.parseModels(CloudClusterPrintJobStatus, print_jobs)
+ self.printers = self.parseModels(ClusterPrinterStatus, printers)
+ self.print_jobs = self.parseModels(ClusterPrintJobStatus, print_jobs)
super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudError.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudError.py
similarity index 88%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudError.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/CloudError.py
index b53361022e..9381e4b8cf 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudError.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudError.py
@@ -1,13 +1,13 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, Optional, Any
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
## Class representing errors generated by the cloud servers, according to the JSON-API standard.
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudError(BaseCloudModel):
+class CloudError(BaseModel):
+
## Creates a new error object.
# \param id: Unique identifier for this particular occurrence of the problem.
# \param title: A short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobResponse.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintJobResponse.py
similarity index 88%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobResponse.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintJobResponse.py
index 79196ee38c..a1880e8751 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobResponse.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintJobResponse.py
@@ -1,13 +1,13 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
# Model that represents the response received from the cloud after requesting to upload a print job
-# Spec: https://api-staging.ultimaker.com/cura/v1/spec
-class CloudPrintJobResponse(BaseCloudModel):
+class CloudPrintJobResponse(BaseModel):
+
## Creates a new print job response model.
# \param job_id: The job unique ID, e.g. 'kBEeZWEifXbrXviO8mRYLx45P8k5lHVGs43XKvRniPg='.
# \param status: The status of the print job.
@@ -28,6 +28,5 @@ class CloudPrintJobResponse(BaseCloudModel):
self.upload_url = upload_url
self.content_type = content_type
self.status_description = status_description
- # TODO: Implement slicing details
self.slicing_details = slicing_details
super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobUploadRequest.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintJobUploadRequest.py
similarity index 77%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobUploadRequest.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintJobUploadRequest.py
index e59c571558..ff705ae495 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobUploadRequest.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintJobUploadRequest.py
@@ -1,11 +1,11 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
# Model that represents the request to upload a print job to the cloud
-# Spec: https://api-staging.ultimaker.com/cura/v1/spec
-class CloudPrintJobUploadRequest(BaseCloudModel):
+class CloudPrintJobUploadRequest(BaseModel):
+
## Creates a new print job upload request.
# \param job_name: The name of the print job.
# \param file_size: The size of the file in bytes.
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintResponse.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintResponse.py
similarity index 85%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintResponse.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintResponse.py
index 919d1b3c3a..b108f40e27 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintResponse.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudPrintResponse.py
@@ -1,14 +1,14 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from datetime import datetime
from typing import Optional, Union
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
# Model that represents the responses received from the cloud after requesting a job to be printed.
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudPrintResponse(BaseCloudModel):
+class CloudPrintResponse(BaseModel):
+
## Creates a new print response object.
# \param job_id: The unique ID of a print job inside of the cluster. This ID is generated by Cura Connect.
# \param status: The status of the print request (queued or failed).
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterBuildPlate.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterBuildPlate.py
new file mode 100644
index 0000000000..a5a392488d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterBuildPlate.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from ..BaseModel import BaseModel
+
+
+## Class representing a cluster printer
+class ClusterBuildPlate(BaseModel):
+
+ ## Create a new build plate
+ # \param type: The type of build plate glass or aluminium
+ def __init__(self, type: str = "glass", **kwargs) -> None:
+ self.type = type
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterMaterial.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterMaterial.py
new file mode 100644
index 0000000000..afc0851211
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterMaterial.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from ..BaseModel import BaseModel
+
+
+class ClusterMaterial(BaseModel):
+ def __init__(self, guid: str, version: int, **kwargs) -> None:
+ self.guid = guid # type: str
+ self.version = version # type: int
+ super().__init__(**kwargs)
+
+ def validate(self) -> None:
+ if not self.guid:
+ raise ValueError("guid is required on ClusterMaterial")
+ if not self.version:
+ raise ValueError("version is required on ClusterMaterial")
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintCoreConfiguration.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintCoreConfiguration.py
similarity index 72%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintCoreConfiguration.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintCoreConfiguration.py
index 7454401d09..e11d2be2d2 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintCoreConfiguration.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintCoreConfiguration.py
@@ -1,26 +1,28 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Union, Dict, Optional, Any
-from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
-from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
-from .CloudClusterPrinterConfigurationMaterial import CloudClusterPrinterConfigurationMaterial
-from .BaseCloudModel import BaseCloudModel
+from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
+from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
+
+from .ClusterPrinterConfigurationMaterial import ClusterPrinterConfigurationMaterial
+from ..BaseModel import BaseModel
-## Class representing a cloud cluster printer configuration
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrintCoreConfiguration(BaseCloudModel):
+## Class representing a cloud cluster printer configuration
+# Also used for representing slots in a Material Station (as from Cura's perspective these are the same).
+class ClusterPrintCoreConfiguration(BaseModel):
+
## Creates a new cloud cluster printer configuration object
# \param extruder_index: The position of the extruder on the machine as list index. Numbered from left to right.
# \param material: The material of a configuration object in a cluster printer. May be in a dict or an object.
# \param nozzle_diameter: The diameter of the print core at this position in millimeters, e.g. '0.4'.
# \param print_core_id: The type of print core inserted at this position, e.g. 'AA 0.4'.
def __init__(self, extruder_index: int,
- material: Union[None, Dict[str, Any], CloudClusterPrinterConfigurationMaterial],
+ material: Union[None, Dict[str, Any], ClusterPrinterConfigurationMaterial] = None,
print_core_id: Optional[str] = None, **kwargs) -> None:
self.extruder_index = extruder_index
- self.material = self.parseModel(CloudClusterPrinterConfigurationMaterial, material) if material else None
+ self.material = self.parseModel(ClusterPrinterConfigurationMaterial, material) if material else None
self.print_core_id = print_core_id
super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConfigurationChange.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobConfigurationChange.py
similarity index 84%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConfigurationChange.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobConfigurationChange.py
index 9ff4154666..88251bbf53 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConfigurationChange.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobConfigurationChange.py
@@ -1,13 +1,13 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
## Model for the types of changes that are needed before a print job can start
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrintJobConfigurationChange(BaseCloudModel):
+class ClusterPrintJobConfigurationChange(BaseModel):
+
## Creates a new print job constraint.
# \param type_of_change: The type of configuration change, one of: "material", "print_core_change"
# \param index: The hotend slot or extruder index to change
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConstraint.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobConstraint.py
similarity index 75%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConstraint.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobConstraint.py
index 8236ec06b9..9239004b18 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConstraint.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobConstraint.py
@@ -1,13 +1,13 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
## Class representing a cloud cluster print job constraint
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrintJobConstraints(BaseCloudModel):
+class ClusterPrintJobConstraints(BaseModel):
+
## Creates a new print job constraint.
# \param require_printer_name: Unique name of the printer that this job should be printed on.
# Should be one of the unique_name field values in the cluster, e.g. 'ultimakersystem-ccbdd30044ec'
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobImpediment.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobImpediment.py
similarity index 68%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobImpediment.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobImpediment.py
index 12b67996c1..5a8f0aa46d 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobImpediment.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobImpediment.py
@@ -1,13 +1,14 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from .BaseCloudModel import BaseCloudModel
+from ..BaseModel import BaseModel
## Class representing the reasons that prevent this job from being printed on the associated printer
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrintJobImpediment(BaseCloudModel):
+class ClusterPrintJobImpediment(BaseModel):
+
## Creates a new print job constraint.
- # \param translation_key: A string indicating a reason the print cannot be printed, such as 'does_not_fit_in_build_volume'
+ # \param translation_key: A string indicating a reason the print cannot be printed,
+ # such as 'does_not_fit_in_build_volume'
# \param severity: A number indicating the severity of the problem, with higher being more severe
def __init__(self, translation_key: str, severity: int, **kwargs) -> None:
self.translation_key = translation_key
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py
similarity index 76%
rename from plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobStatus.py
rename to plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py
index 45b7d838a5..9794da1bbb 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobStatus.py
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py
@@ -1,22 +1,23 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import List, Optional, Union, Dict, Any
-from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-from ...UM3PrintJobOutputModel import UM3PrintJobOutputModel
-from ...ConfigurationChangeModel import ConfigurationChangeModel
-from ..CloudOutputController import CloudOutputController
-from .BaseCloudModel import BaseCloudModel
-from .CloudClusterBuildPlate import CloudClusterBuildPlate
-from .CloudClusterPrintJobConfigurationChange import CloudClusterPrintJobConfigurationChange
-from .CloudClusterPrintJobImpediment import CloudClusterPrintJobImpediment
-from .CloudClusterPrintCoreConfiguration import CloudClusterPrintCoreConfiguration
-from .CloudClusterPrintJobConstraint import CloudClusterPrintJobConstraints
+from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
+
+from .ClusterBuildPlate import ClusterBuildPlate
+from .ClusterPrintJobConfigurationChange import ClusterPrintJobConfigurationChange
+from .ClusterPrintJobImpediment import ClusterPrintJobImpediment
+from .ClusterPrintCoreConfiguration import ClusterPrintCoreConfiguration
+from .ClusterPrintJobConstraint import ClusterPrintJobConstraints
+from ..UM3PrintJobOutputModel import UM3PrintJobOutputModel
+from ..ConfigurationChangeModel import ConfigurationChangeModel
+from ..BaseModel import BaseModel
+from ...ClusterOutputController import ClusterOutputController
## Model for the status of a single print job in a cluster.
-# Spec: https://api-staging.ultimaker.com/connect/v1/spec
-class CloudClusterPrintJobStatus(BaseCloudModel):
+class ClusterPrintJobStatus(BaseModel):
+
## Creates a new cloud print job status model.
# \param assigned_to: The name of the printer this job is assigned to while being queued.
# \param configuration: The required print core configurations of this print job.
@@ -45,21 +46,21 @@ class CloudClusterPrintJobStatus(BaseCloudModel):
# printer
def __init__(self, created_at: str, force: bool, machine_variant: str, name: str, started: bool, status: str,
time_total: int, uuid: str,
- configuration: List[Union[Dict[str, Any], CloudClusterPrintCoreConfiguration]],
- constraints: List[Union[Dict[str, Any], CloudClusterPrintJobConstraints]],
+ configuration: List[Union[Dict[str, Any], ClusterPrintCoreConfiguration]],
+ constraints: List[Union[Dict[str, Any], ClusterPrintJobConstraints]],
last_seen: Optional[float] = None, network_error_count: Optional[int] = None,
owner: Optional[str] = None, printer_uuid: Optional[str] = None, time_elapsed: Optional[int] = None,
assigned_to: Optional[str] = None, deleted_at: Optional[str] = None,
printed_on_uuid: Optional[str] = None,
configuration_changes_required: List[
- Union[Dict[str, Any], CloudClusterPrintJobConfigurationChange]] = None,
- build_plate: Union[Dict[str, Any], CloudClusterBuildPlate] = None,
+ Union[Dict[str, Any], ClusterPrintJobConfigurationChange]] = None,
+ build_plate: Union[Dict[str, Any], ClusterBuildPlate] = None,
compatible_machine_families: List[str] = None,
- impediments_to_printing: List[Union[Dict[str, Any], CloudClusterPrintJobImpediment]] = None,
+ impediments_to_printing: List[Union[Dict[str, Any], ClusterPrintJobImpediment]] = None,
**kwargs) -> None:
self.assigned_to = assigned_to
- self.configuration = self.parseModels(CloudClusterPrintCoreConfiguration, configuration)
- self.constraints = self.parseModels(CloudClusterPrintJobConstraints, constraints)
+ self.configuration = self.parseModels(ClusterPrintCoreConfiguration, configuration)
+ self.constraints = self.parseModels(ClusterPrintJobConstraints, constraints)
self.created_at = created_at
self.force = force
self.last_seen = last_seen
@@ -76,29 +77,29 @@ class CloudClusterPrintJobStatus(BaseCloudModel):
self.deleted_at = deleted_at
self.printed_on_uuid = printed_on_uuid
- self.configuration_changes_required = self.parseModels(CloudClusterPrintJobConfigurationChange,
+ self.configuration_changes_required = self.parseModels(ClusterPrintJobConfigurationChange,
configuration_changes_required) \
if configuration_changes_required else []
- self.build_plate = self.parseModel(CloudClusterBuildPlate, build_plate) if build_plate else None
+ self.build_plate = self.parseModel(ClusterBuildPlate, build_plate) if build_plate else None
self.compatible_machine_families = compatible_machine_families if compatible_machine_families else []
- self.impediments_to_printing = self.parseModels(CloudClusterPrintJobImpediment, impediments_to_printing) \
+ self.impediments_to_printing = self.parseModels(ClusterPrintJobImpediment, impediments_to_printing) \
if impediments_to_printing else []
super().__init__(**kwargs)
## Creates an UM3 print job output model based on this cloud cluster print job.
# \param printer: The output model of the printer
- def createOutputModel(self, controller: CloudOutputController) -> UM3PrintJobOutputModel:
+ def createOutputModel(self, controller: ClusterOutputController) -> UM3PrintJobOutputModel:
model = UM3PrintJobOutputModel(controller, self.uuid, self.name)
self.updateOutputModel(model)
-
return model
## Creates a new configuration model
- def _createConfigurationModel(self) -> ConfigurationModel:
+ def _createConfigurationModel(self) -> PrinterConfigurationModel:
extruders = [extruder.createConfigurationModel() for extruder in self.configuration or ()]
- configuration = ConfigurationModel()
+ configuration = PrinterConfigurationModel()
configuration.setExtruderConfigurations(extruders)
+ configuration.setPrinterType(self.machine_variant)
return configuration
## Updates an UM3 print job output model based on this cloud cluster print job.
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterConfigurationMaterial.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterConfigurationMaterial.py
new file mode 100644
index 0000000000..8edb9fb808
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterConfigurationMaterial.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional
+
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
+
+from ..BaseModel import BaseModel
+
+
+## Class representing a cloud cluster printer configuration
+class ClusterPrinterConfigurationMaterial(BaseModel):
+
+ ## Creates a new material configuration model.
+ # \param brand: The brand of material in this print core, e.g. 'Ultimaker'.
+ # \param color: The color of material in this print core, e.g. 'Blue'.
+ # \param guid: he GUID of the material in this print core, e.g. '506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9'.
+ # \param material: The type of material in this print core, e.g. 'PLA'.
+ def __init__(self, brand: Optional[str] = None, color: Optional[str] = None, guid: Optional[str] = None,
+ material: Optional[str] = None, **kwargs) -> None:
+ self.guid = guid
+ self.brand = brand
+ self.color = color
+ self.material = material
+ super().__init__(**kwargs)
+
+ ## Creates a material output model based on this cloud printer material.
+ #
+ # A material is chosen that matches the current GUID. If multiple such
+ # materials are available, read-only materials are preferred and the
+ # material with the earliest alphabetical name will be selected.
+ # \return A material output model that matches the current GUID.
+ def createOutputModel(self) -> MaterialOutputModel:
+ container_registry = ContainerRegistry.getInstance()
+ same_guid = container_registry.findInstanceContainersMetadata(GUID = self.guid)
+ if same_guid:
+ read_only = sorted(filter(lambda metadata: container_registry.isReadOnly(metadata["id"]), same_guid), key = lambda metadata: metadata["name"])
+ if read_only:
+ material_metadata = read_only[0]
+ else:
+ material_metadata = min(same_guid, key = lambda metadata: metadata["name"])
+ else:
+ material_metadata = {
+ "color_code": self.color,
+ "brand": self.brand,
+ "material": self.material,
+ "name": "Empty" if self.material == "empty" else "Unknown"
+ }
+
+ return MaterialOutputModel(guid = self.guid, type = material_metadata["material"], brand = material_metadata["brand"], color = material_metadata["color_code"], name = material_metadata["name"])
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterMaterialStation.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterMaterialStation.py
new file mode 100644
index 0000000000..c51e07bcfc
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterMaterialStation.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Union, Dict, Any, List
+
+from ..BaseModel import BaseModel
+from .ClusterPrinterMaterialStationSlot import ClusterPrinterMaterialStationSlot
+
+
+## Class representing the data of a Material Station in the cluster.
+class ClusterPrinterMaterialStation(BaseModel):
+
+ ## Creates a new Material Station status.
+ # \param status: The status of the material station.
+ # \param: supported: Whether the material station is supported on this machine or not.
+ # \param material_slots: The active slots configurations of this material station.
+ def __init__(self, status: str, supported: bool = False,
+ material_slots: List[Union[ClusterPrinterMaterialStationSlot, Dict[str, Any]]] = None,
+ **kwargs) -> None:
+ self.status = status
+ self.supported = supported
+ self.material_slots = self.parseModels(ClusterPrinterMaterialStationSlot, material_slots)\
+ if material_slots else [] # type: List[ClusterPrinterMaterialStationSlot]
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterMaterialStationSlot.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterMaterialStationSlot.py
new file mode 100644
index 0000000000..80deb1c9a8
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterMaterialStationSlot.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional
+
+from .ClusterPrintCoreConfiguration import ClusterPrintCoreConfiguration
+
+
+## Class representing the data of a single slot in the material station.
+class ClusterPrinterMaterialStationSlot(ClusterPrintCoreConfiguration):
+
+ ## Create a new material station slot object.
+ # \param slot_index: The index of the slot in the material station (ranging 0 to 5).
+ # \param compatible: Whether the configuration is compatible with the print core.
+ # \param material_remaining: How much material is remaining on the spool (between 0 and 1, or -1 for missing data).
+ # \param material_empty: Whether the material spool is too empty to be used.
+ def __init__(self, slot_index: int, compatible: bool, material_remaining: float,
+ material_empty: Optional[bool] = False, **kwargs):
+ self.slot_index = slot_index
+ self.compatible = compatible
+ self.material_remaining = material_remaining
+ self.material_empty = material_empty
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py
new file mode 100644
index 0000000000..2e0912f057
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py
@@ -0,0 +1,147 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from itertools import product
+from typing import List, Union, Dict, Optional, Any
+
+from PyQt5.QtCore import QUrl
+
+from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
+from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
+from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
+
+from .ClusterBuildPlate import ClusterBuildPlate
+from .ClusterPrintCoreConfiguration import ClusterPrintCoreConfiguration
+from .ClusterPrinterMaterialStation import ClusterPrinterMaterialStation
+from .ClusterPrinterMaterialStationSlot import ClusterPrinterMaterialStationSlot
+from .ClusterPrinterConfigurationMaterial import ClusterPrinterConfigurationMaterial
+from ..BaseModel import BaseModel
+
+
+## Class representing a cluster printer
+class ClusterPrinterStatus(BaseModel):
+
+ ## Creates a new cluster printer status
+ # \param enabled: A printer can be disabled if it should not receive new jobs. By default every printer is enabled.
+ # \param firmware_version: Firmware version installed on the printer. Can differ for each printer in a cluster.
+ # \param friendly_name: Human readable name of the printer. Can be used for identification purposes.
+ # \param ip_address: The IP address of the printer in the local network.
+ # \param machine_variant: The type of printer. Can be 'Ultimaker 3' or 'Ultimaker 3ext'.
+ # \param status: The status of the printer.
+ # \param unique_name: The unique name of the printer in the network.
+ # \param uuid: The unique ID of the printer, also known as GUID.
+ # \param configuration: The active print core configurations of this printer.
+ # \param reserved_by: A printer can be claimed by a specific print job.
+ # \param maintenance_required: Indicates if maintenance is necessary.
+ # \param firmware_update_status: Whether the printer's firmware is up-to-date, value is one of: "up_to_date",
+ # "pending_update", "update_available", "update_in_progress", "update_failed", "update_impossible".
+ # \param latest_available_firmware: The version of the latest firmware that is available.
+ # \param build_plate: The build plate that is on the printer.
+ # \param material_station: The material station that is on the printer.
+ def __init__(self, enabled: bool, firmware_version: str, friendly_name: str, ip_address: str, machine_variant: str,
+ status: str, unique_name: str, uuid: str,
+ configuration: List[Union[Dict[str, Any], ClusterPrintCoreConfiguration]],
+ reserved_by: Optional[str] = None, maintenance_required: Optional[bool] = None,
+ firmware_update_status: Optional[str] = None, latest_available_firmware: Optional[str] = None,
+ build_plate: Union[Dict[str, Any], ClusterBuildPlate] = None,
+ material_station: Union[Dict[str, Any], ClusterPrinterMaterialStation] = None, **kwargs) -> None:
+
+ self.configuration = self.parseModels(ClusterPrintCoreConfiguration, configuration)
+ self.enabled = enabled
+ self.firmware_version = firmware_version
+ self.friendly_name = friendly_name
+ self.ip_address = ip_address
+ self.machine_variant = machine_variant
+ self.status = status
+ self.unique_name = unique_name
+ self.uuid = uuid
+ self.reserved_by = reserved_by
+ self.maintenance_required = maintenance_required
+ self.firmware_update_status = firmware_update_status
+ self.latest_available_firmware = latest_available_firmware
+ self.build_plate = self.parseModel(ClusterBuildPlate, build_plate) if build_plate else None
+ self.material_station = self.parseModel(ClusterPrinterMaterialStation,
+ material_station) if material_station else None
+ super().__init__(**kwargs)
+
+ ## Creates a new output model.
+ # \param controller - The controller of the model.
+ def createOutputModel(self, controller: PrinterOutputController) -> PrinterOutputModel:
+ # FIXME
+ # Note that we're using '2' here as extruder count. We have hardcoded this for now to prevent issues where the
+ # amount of extruders coming back from the API is actually lower (which it can be if a printer was just added
+ # to a cluster). This should be fixed in the future, probably also on the cluster API side.
+ model = PrinterOutputModel(controller, 2, firmware_version = self.firmware_version)
+ self.updateOutputModel(model)
+ return model
+
+ ## Updates the given output model.
+ # \param model - The output model to update.
+ def updateOutputModel(self, model: PrinterOutputModel) -> None:
+ model.updateKey(self.uuid)
+ model.updateName(self.friendly_name)
+ model.updateUniqueName(self.unique_name)
+ model.updateType(self.machine_variant)
+ model.updateState(self.status if self.enabled else "disabled")
+ model.updateBuildplate(self.build_plate.type if self.build_plate else "glass")
+ model.setCameraUrl(QUrl("http://{}:8080/?action=stream".format(self.ip_address)))
+
+ if not model.printerConfiguration:
+ # Prevent accessing printer configuration when not available.
+ # This sometimes happens when a printer was just added to a group and Cura is connected to that group.
+ return
+
+ # Set the possible configurations based on whether a Material Station is present or not.
+ if self.material_station and self.material_station.material_slots:
+ self._updateAvailableConfigurations(model)
+ if self.configuration:
+ self._updateActiveConfiguration(model)
+
+ def _updateActiveConfiguration(self, model: PrinterOutputModel) -> None:
+ configurations = zip(self.configuration, model.extruders, model.printerConfiguration.extruderConfigurations)
+ for configuration, extruder_output, extruder_config in configurations:
+ configuration.updateOutputModel(extruder_output)
+ configuration.updateConfigurationModel(extruder_config)
+
+ def _updateAvailableConfigurations(self, model: PrinterOutputModel) -> None:
+ available_configurations = [self._createAvailableConfigurationFromPrinterConfiguration(
+ left_slot = left_slot,
+ right_slot = right_slot,
+ printer_configuration = model.printerConfiguration
+ ) for left_slot, right_slot in product(self._getSlotsForExtruder(0), self._getSlotsForExtruder(1))]
+ model.setAvailableConfigurations(available_configurations)
+
+ ## Create a list of Material Station slots for the given extruder index.
+ # Returns a list with a single empty material slot if none are found to ensure we don't miss configurations.
+ def _getSlotsForExtruder(self, extruder_index: int) -> List[ClusterPrinterMaterialStationSlot]:
+ if not self.material_station: # typing guard
+ return []
+ slots = [slot for slot in self.material_station.material_slots if self._isSupportedConfiguration(
+ slot = slot,
+ extruder_index = extruder_index
+ )]
+ return slots or [self._createEmptyMaterialSlot(extruder_index)]
+
+ ## Check if a configuration is supported in order to make it selectable by the user.
+ # We filter out any slot that is not supported by the extruder index, print core type or if the material is empty.
+ @staticmethod
+ def _isSupportedConfiguration(slot: ClusterPrinterMaterialStationSlot, extruder_index: int) -> bool:
+ return slot.extruder_index == extruder_index and slot.compatible and not slot.material_empty
+
+ ## Create an empty material slot with a fake empty material.
+ @staticmethod
+ def _createEmptyMaterialSlot(extruder_index: int) -> ClusterPrinterMaterialStationSlot:
+ empty_material = ClusterPrinterConfigurationMaterial(guid = "", material = "empty", brand = "", color = "")
+ return ClusterPrinterMaterialStationSlot(slot_index = 0, extruder_index = extruder_index,
+ compatible = True, material_remaining = 0, material = empty_material)
+
+ @staticmethod
+ def _createAvailableConfigurationFromPrinterConfiguration(left_slot: ClusterPrinterMaterialStationSlot,
+ right_slot: ClusterPrinterMaterialStationSlot,
+ printer_configuration: PrinterConfigurationModel
+ ) -> PrinterConfigurationModel:
+ available_configuration = PrinterConfigurationModel()
+ available_configuration.setExtruderConfigurations([left_slot.createConfigurationModel(),
+ right_slot.createConfigurationModel()])
+ available_configuration.setPrinterType(printer_configuration.printerType)
+ available_configuration.setBuildplateConfiguration(printer_configuration.buildplateConfiguration)
+ return available_configuration
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/PrinterSystemStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/PrinterSystemStatus.py
new file mode 100644
index 0000000000..ad7b9c8698
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/Http/PrinterSystemStatus.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Dict, Any
+
+from ..BaseModel import BaseModel
+
+
+## Class representing the system status of a printer.
+class PrinterSystemStatus(BaseModel):
+
+ def __init__(self, guid: str, firmware: str, hostname: str, name: str, platform: str, variant: str,
+ hardware: Dict[str, Any], **kwargs
+ ) -> None:
+ self.guid = guid
+ self.firmware = firmware
+ self.hostname = hostname
+ self.name = name
+ self.platform = platform
+ self.variant = variant
+ self.hardware = hardware
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/__init__.py b/plugins/UM3NetworkPrinting/src/Models/Http/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/UM3NetworkPrinting/src/Models/LocalMaterial.py b/plugins/UM3NetworkPrinting/src/Models/LocalMaterial.py
new file mode 100644
index 0000000000..b45289e1c4
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models/LocalMaterial.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from .BaseModel import BaseModel
+
+
+class LocalMaterial(BaseModel):
+
+ def __init__(self, GUID: str, id: str, version: int, **kwargs) -> None:
+ self.GUID = GUID # type: str
+ self.id = id # type: str
+ self.version = version # type: int
+ super().__init__(**kwargs)
+
+ def validate(self) -> None:
+ super().validate()
+ if not self.GUID:
+ raise ValueError("guid is required on LocalMaterial")
+ if not self.version:
+ raise ValueError("version is required on LocalMaterial")
+ if not self.id:
+ raise ValueError("id is required on LocalMaterial")
diff --git a/plugins/UM3NetworkPrinting/src/UM3PrintJobOutputModel.py b/plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py
similarity index 64%
rename from plugins/UM3NetworkPrinting/src/UM3PrintJobOutputModel.py
rename to plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py
index 4f44ca4af8..bfde233a35 100644
--- a/plugins/UM3NetworkPrinting/src/UM3PrintJobOutputModel.py
+++ b/plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py
@@ -1,21 +1,22 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-
from typing import List
from PyQt5.QtCore import pyqtProperty, pyqtSignal
+from PyQt5.QtGui import QImage
-from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
+from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
+
from .ConfigurationChangeModel import ConfigurationChangeModel
class UM3PrintJobOutputModel(PrintJobOutputModel):
configurationChangesChanged = pyqtSignal()
- def __init__(self, output_controller: "PrinterOutputController", key: str = "", name: str = "", parent=None) -> None:
+ def __init__(self, output_controller: PrinterOutputController, key: str = "", name: str = "", parent=None) -> None:
super().__init__(output_controller, key, name, parent)
- self._configuration_changes = [] # type: List[ConfigurationChangeModel]
+ self._configuration_changes = [] # type: List[ConfigurationChangeModel]
@pyqtProperty("QVariantList", notify=configurationChangesChanged)
def configurationChanges(self) -> List[ConfigurationChangeModel]:
@@ -26,3 +27,8 @@ class UM3PrintJobOutputModel(PrintJobOutputModel):
return
self._configuration_changes = changes
self.configurationChangesChanged.emit()
+
+ def updatePreviewImageData(self, data: bytes) -> None:
+ image = QImage()
+ image.loadFromData(data)
+ self.updatePreviewImage(image)
diff --git a/plugins/UM3NetworkPrinting/src/Models/__init__.py b/plugins/UM3NetworkPrinting/src/Models/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py
new file mode 100644
index 0000000000..6a8b9f625c
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py
@@ -0,0 +1,173 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import json
+from json import JSONDecodeError
+from typing import Callable, List, Optional, Dict, Union, Any, Type, cast, TypeVar, Tuple
+
+from PyQt5.QtCore import QUrl
+from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
+
+from UM.Logger import Logger
+
+from ..Models.BaseModel import BaseModel
+from ..Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
+from ..Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
+from ..Models.Http.PrinterSystemStatus import PrinterSystemStatus
+from ..Models.Http.ClusterMaterial import ClusterMaterial
+
+
+## The generic type variable used to document the methods below.
+ClusterApiClientModel = TypeVar("ClusterApiClientModel", bound=BaseModel)
+
+
+## The ClusterApiClient is responsible for all network calls to local network clusters.
+class ClusterApiClient:
+
+ PRINTER_API_PREFIX = "/api/v1"
+ CLUSTER_API_PREFIX = "/cluster-api/v1"
+
+ # In order to avoid garbage collection we keep the callbacks in this list.
+ _anti_gc_callbacks = [] # type: List[Callable[[], None]]
+
+ ## Initializes a new cluster API client.
+ # \param address: The network address of the cluster to call.
+ # \param on_error: The callback to be called whenever we receive errors from the server.
+ def __init__(self, address: str, on_error: Callable) -> None:
+ super().__init__()
+ self._manager = QNetworkAccessManager()
+ self._address = address
+ self._on_error = on_error
+
+ ## Get printer system information.
+ # \param on_finished: The callback in case the response is successful.
+ def getSystem(self, on_finished: Callable) -> None:
+ url = "{}/system".format(self.PRINTER_API_PREFIX)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished, PrinterSystemStatus)
+
+ ## Get the installed materials on the printer.
+ # \param on_finished: The callback in case the response is successful.
+ def getMaterials(self, on_finished: Callable[[List[ClusterMaterial]], Any]) -> None:
+ url = "{}/materials".format(self.CLUSTER_API_PREFIX)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished, ClusterMaterial)
+
+ ## Get the printers in the cluster.
+ # \param on_finished: The callback in case the response is successful.
+ def getPrinters(self, on_finished: Callable[[List[ClusterPrinterStatus]], Any]) -> None:
+ url = "{}/printers".format(self.CLUSTER_API_PREFIX)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished, ClusterPrinterStatus)
+
+ ## Get the print jobs in the cluster.
+ # \param on_finished: The callback in case the response is successful.
+ def getPrintJobs(self, on_finished: Callable[[List[ClusterPrintJobStatus]], Any]) -> None:
+ url = "{}/print_jobs".format(self.CLUSTER_API_PREFIX)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished, ClusterPrintJobStatus)
+
+ ## Move a print job to the top of the queue.
+ def movePrintJobToTop(self, print_job_uuid: str) -> None:
+ url = "{}/print_jobs/{}/action/move".format(self.CLUSTER_API_PREFIX, print_job_uuid)
+ self._manager.post(self._createEmptyRequest(url), json.dumps({"to_position": 0, "list": "queued"}).encode())
+
+ ## Override print job configuration and force it to be printed.
+ def forcePrintJob(self, print_job_uuid: str) -> None:
+ url = "{}/print_jobs/{}".format(self.CLUSTER_API_PREFIX, print_job_uuid)
+ self._manager.put(self._createEmptyRequest(url), json.dumps({"force": True}).encode())
+
+ ## Delete a print job from the queue.
+ def deletePrintJob(self, print_job_uuid: str) -> None:
+ url = "{}/print_jobs/{}".format(self.CLUSTER_API_PREFIX, print_job_uuid)
+ self._manager.deleteResource(self._createEmptyRequest(url))
+
+ ## Set the state of a print job.
+ def setPrintJobState(self, print_job_uuid: str, state: str) -> None:
+ url = "{}/print_jobs/{}/action".format(self.CLUSTER_API_PREFIX, print_job_uuid)
+ # We rewrite 'resume' to 'print' here because we are using the old print job action endpoints.
+ action = "print" if state == "resume" else state
+ self._manager.put(self._createEmptyRequest(url), json.dumps({"action": action}).encode())
+
+ ## Get the preview image data of a print job.
+ def getPrintJobPreviewImage(self, print_job_uuid: str, on_finished: Callable) -> None:
+ url = "{}/print_jobs/{}/preview_image".format(self.CLUSTER_API_PREFIX, print_job_uuid)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished)
+
+ ## We override _createEmptyRequest in order to add the user credentials.
+ # \param url: The URL to request
+ # \param content_type: The type of the body contents.
+ def _createEmptyRequest(self, path: str, content_type: Optional[str] = "application/json") -> QNetworkRequest:
+ url = QUrl("http://" + self._address + path)
+ request = QNetworkRequest(url)
+ request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True)
+ if content_type:
+ request.setHeader(QNetworkRequest.ContentTypeHeader, content_type)
+ return request
+
+ ## Parses the given JSON network reply into a status code and a dictionary, handling unexpected errors as well.
+ # \param reply: The reply from the server.
+ # \return A tuple with a status code and a dictionary.
+ @staticmethod
+ def _parseReply(reply: QNetworkReply) -> Tuple[int, Dict[str, Any]]:
+ status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
+ try:
+ response = bytes(reply.readAll()).decode()
+ return status_code, json.loads(response)
+ except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
+ Logger.logException("e", "Could not parse the cluster response: %s", err)
+ return status_code, {"errors": [err]}
+
+ ## Parses the given models and calls the correct callback depending on the result.
+ # \param response: The response from the server, after being converted to a dict.
+ # \param on_finished: The callback in case the response is successful.
+ # \param model_class: The type of the model to convert the response to. It may either be a single record or a list.
+ def _parseModels(self, response: Dict[str, Any],
+ on_finished: Union[Callable[[ClusterApiClientModel], Any],
+ Callable[[List[ClusterApiClientModel]], Any]],
+ model_class: Type[ClusterApiClientModel]) -> None:
+ try:
+ if isinstance(response, list):
+ results = [model_class(**c) for c in response] # type: List[ClusterApiClientModel]
+ on_finished_list = cast(Callable[[List[ClusterApiClientModel]], Any], on_finished)
+ on_finished_list(results)
+ else:
+ result = model_class(**response) # type: ClusterApiClientModel
+ on_finished_item = cast(Callable[[ClusterApiClientModel], Any], on_finished)
+ on_finished_item(result)
+ except (JSONDecodeError, TypeError, ValueError):
+ Logger.log("e", "Could not parse response from network: %s", str(response))
+
+ ## Creates a callback function so that it includes the parsing of the response into the correct model.
+ # The callback is added to the 'finished' signal of the reply.
+ # \param reply: The reply that should be listened to.
+ # \param on_finished: The callback in case the response is successful.
+ def _addCallback(self,
+ reply: QNetworkReply,
+ on_finished: Union[Callable[[ClusterApiClientModel], Any],
+ Callable[[List[ClusterApiClientModel]], Any]],
+ model: Type[ClusterApiClientModel] = None,
+ ) -> None:
+
+ def parse() -> None:
+ self._anti_gc_callbacks.remove(parse)
+
+ # Don't try to parse the reply if we didn't get one
+ if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None:
+ return
+
+ if reply.error() > 0:
+ self._on_error(reply.errorString())
+ return
+
+ # If no parse model is given, simply return the raw data in the callback.
+ if not model:
+ on_finished(reply.readAll())
+ return
+
+ # Otherwise parse the result and return the formatted data in the callback.
+ status_code, response = self._parseReply(reply)
+ self._parseModels(response, on_finished, model)
+
+ self._anti_gc_callbacks.append(parse)
+ reply.finished.connect(parse)
diff --git a/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py
new file mode 100644
index 0000000000..1266afcca8
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py
@@ -0,0 +1,209 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import os
+from typing import Optional, Dict, List, Callable, Any
+
+from PyQt5.QtGui import QDesktopServices
+from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
+from PyQt5.QtNetwork import QNetworkReply
+
+from UM.FileHandler.FileHandler import FileHandler
+from UM.i18n import i18nCatalog
+from UM.Logger import Logger
+from UM.Scene.SceneNode import SceneNode
+from cura.CuraApplication import CuraApplication
+from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
+
+from .ClusterApiClient import ClusterApiClient
+from .SendMaterialJob import SendMaterialJob
+from ..ExportFileJob import ExportFileJob
+from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
+from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage
+from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage
+from ..Messages.PrintJobUploadSuccessMessage import PrintJobUploadSuccessMessage
+from ..Models.Http.ClusterMaterial import ClusterMaterial
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice):
+
+ activeCameraUrlChanged = pyqtSignal()
+
+ def __init__(self, device_id: str, address: str, properties: Dict[bytes, bytes], parent=None) -> None:
+
+ super().__init__(
+ device_id=device_id,
+ address=address,
+ properties=properties,
+ connection_type=ConnectionType.NetworkConnection,
+ parent=parent
+ )
+
+ self._cluster_api = None # type: Optional[ClusterApiClient]
+ self._active_exported_job = None # type: Optional[ExportFileJob]
+ self._printer_select_dialog = None # type: Optional[QObject]
+
+ # We don't have authentication over local networking, so we're always authenticated.
+ self.setAuthenticationState(AuthState.Authenticated)
+ self._setInterfaceElements()
+ self._active_camera_url = QUrl() # type: QUrl
+
+ ## Set all the interface elements and texts for this output device.
+ def _setInterfaceElements(self) -> None:
+ self.setPriority(3) # Make sure the output device gets selected above local file output
+ self.setShortDescription(I18N_CATALOG.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
+ self.setDescription(I18N_CATALOG.i18nc("@properties:tooltip", "Print over network"))
+ self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected over the network"))
+
+ ## Called when the connection to the cluster changes.
+ def connect(self) -> None:
+ super().connect()
+ self._update()
+ self.sendMaterialProfiles()
+
+ @pyqtProperty(QUrl, notify=activeCameraUrlChanged)
+ def activeCameraUrl(self) -> QUrl:
+ return self._active_camera_url
+
+ @pyqtSlot(QUrl, name="setActiveCameraUrl")
+ def setActiveCameraUrl(self, camera_url: QUrl) -> None:
+ if self._active_camera_url != camera_url:
+ self._active_camera_url = camera_url
+ self.activeCameraUrlChanged.emit()
+
+ @pyqtSlot(name="openPrintJobControlPanel")
+ def openPrintJobControlPanel(self) -> None:
+ QDesktopServices.openUrl(QUrl("http://" + self._address + "/print_jobs"))
+
+ @pyqtSlot(name="openPrinterControlPanel")
+ def openPrinterControlPanel(self) -> None:
+ QDesktopServices.openUrl(QUrl("http://" + self._address + "/printers"))
+
+ @pyqtSlot(str, name="sendJobToTop")
+ def sendJobToTop(self, print_job_uuid: str) -> None:
+ self._getApiClient().movePrintJobToTop(print_job_uuid)
+
+ @pyqtSlot(str, name="deleteJobFromQueue")
+ def deleteJobFromQueue(self, print_job_uuid: str) -> None:
+ self._getApiClient().deletePrintJob(print_job_uuid)
+
+ @pyqtSlot(str, name="forceSendJob")
+ def forceSendJob(self, print_job_uuid: str) -> None:
+ self._getApiClient().forcePrintJob(print_job_uuid)
+
+ ## Set the remote print job state.
+ # \param print_job_uuid: The UUID of the print job to set the state for.
+ # \param action: The action to undertake ('pause', 'resume', 'abort').
+ def setJobState(self, print_job_uuid: str, action: str) -> None:
+ self._getApiClient().setPrintJobState(print_job_uuid, action)
+
+ def _update(self) -> None:
+ super()._update()
+ self._getApiClient().getPrinters(self._updatePrinters)
+ self._getApiClient().getPrintJobs(self._updatePrintJobs)
+ self._updatePrintJobPreviewImages()
+
+ ## Get a list of materials that are installed on the cluster host.
+ def getMaterials(self, on_finished: Callable[[List[ClusterMaterial]], Any]) -> None:
+ self._getApiClient().getMaterials(on_finished = on_finished)
+
+ ## Sync the material profiles in Cura with the printer.
+ # This gets called when connecting to a printer as well as when sending a print.
+ def sendMaterialProfiles(self) -> None:
+ job = SendMaterialJob(device = self)
+ job.run()
+
+ ## Send a print job to the cluster.
+ def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
+ file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
+
+ # Show an error message if we're already sending a job.
+ if self._progress.visible:
+ PrintJobUploadBlockedMessage().show()
+ return
+
+ self.writeStarted.emit(self)
+
+ # Export the scene to the correct file type.
+ job = ExportFileJob(file_handler=file_handler, nodes=nodes, firmware_version=self.firmwareVersion)
+ job.finished.connect(self._onPrintJobCreated)
+ job.start()
+
+ ## Allows the user to choose a printer to print with from the printer selection dialogue.
+ # \param unique_name: The unique name of the printer to target.
+ @pyqtSlot(str, name="selectTargetPrinter")
+ def selectTargetPrinter(self, unique_name: str = "") -> None:
+ self._startPrintJobUpload(unique_name if unique_name != "" else None)
+
+ ## Handler for when the print job was created locally.
+ # It can now be sent over the network.
+ def _onPrintJobCreated(self, job: ExportFileJob) -> None:
+ self._active_exported_job = job
+ # TODO: add preference to enable/disable this feature?
+ if self.clusterSize > 1:
+ self._showPrinterSelectionDialog() # self._startPrintJobUpload will be triggered from this dialog
+ return
+ self._startPrintJobUpload()
+
+ ## Shows a dialog allowing the user to select which printer in a group to send a job to.
+ def _showPrinterSelectionDialog(self) -> None:
+ if not self._printer_select_dialog:
+ plugin_path = CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or ""
+ path = os.path.join(plugin_path, "resources", "qml", "PrintWindow.qml")
+ self._printer_select_dialog = CuraApplication.getInstance().createQmlComponent(path, {"OutputDevice": self})
+ if self._printer_select_dialog is not None:
+ self._printer_select_dialog.show()
+
+ ## Upload the print job to the group.
+ def _startPrintJobUpload(self, unique_name: str = None) -> None:
+ if not self._active_exported_job:
+ Logger.log("e", "No active exported job to upload!")
+ return
+ self._progress.show()
+ parts = [
+ self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain"),
+ self._createFormPart("name=\"file\"; filename=\"%s\"" % self._active_exported_job.getFileName(),
+ self._active_exported_job.getOutput())
+ ]
+ # If a specific printer was selected we include the name in the request.
+ # FIXME: Connect should allow the printer UUID here instead of the 'unique_name'.
+ if unique_name is not None:
+ parts.append(self._createFormPart("name=require_printer_name", bytes(unique_name, "utf-8"), "text/plain"))
+ # FIXME: move form posting to API client
+ self.postFormWithParts("/cluster-api/v1/print_jobs/", parts, on_finished=self._onPrintUploadCompleted,
+ on_progress=self._onPrintJobUploadProgress)
+ self._active_exported_job = None
+
+ ## Handler for print job upload progress.
+ def _onPrintJobUploadProgress(self, bytes_sent: int, bytes_total: int) -> None:
+ percentage = (bytes_sent / bytes_total) if bytes_total else 0
+ self._progress.setProgress(percentage * 100)
+ self.writeProgress.emit()
+
+ ## Handler for when the print job was fully uploaded to the cluster.
+ def _onPrintUploadCompleted(self, _: QNetworkReply) -> None:
+ self._progress.hide()
+ PrintJobUploadSuccessMessage().show()
+ self.writeFinished.emit()
+
+ ## Displays the given message if uploading the mesh has failed
+ # \param message: The message to display.
+ def _onUploadError(self, message: str = None) -> None:
+ self._progress.hide()
+ PrintJobUploadErrorMessage(message).show()
+ self.writeError.emit()
+
+ ## Download all the images from the cluster and load their data in the print job models.
+ def _updatePrintJobPreviewImages(self):
+ for print_job in self._print_jobs:
+ if print_job.getPreviewImage() is None:
+ self._getApiClient().getPrintJobPreviewImage(print_job.key, print_job.updatePreviewImageData)
+
+ ## Get the API client instance.
+ def _getApiClient(self) -> ClusterApiClient:
+ if not self._cluster_api:
+ self._cluster_api = ClusterApiClient(self.address, on_error = lambda error: Logger.log("e", str(error)))
+ return self._cluster_api
diff --git a/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py
new file mode 100644
index 0000000000..273c64ef4d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py
@@ -0,0 +1,274 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Dict, Optional, Callable, List
+
+from UM import i18nCatalog
+from UM.Logger import Logger
+from UM.Signal import Signal
+from UM.Version import Version
+
+from cura.CuraApplication import CuraApplication
+from cura.Settings.CuraStackBuilder import CuraStackBuilder
+from cura.Settings.GlobalStack import GlobalStack
+
+from .ZeroConfClient import ZeroConfClient
+from .ClusterApiClient import ClusterApiClient
+from .LocalClusterOutputDevice import LocalClusterOutputDevice
+from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
+from ..Messages.CloudFlowMessage import CloudFlowMessage
+from ..Messages.LegacyDeviceNoLongerSupportedMessage import LegacyDeviceNoLongerSupportedMessage
+from ..Models.Http.PrinterSystemStatus import PrinterSystemStatus
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## The LocalClusterOutputDeviceManager is responsible for discovering and managing local networked clusters.
+class LocalClusterOutputDeviceManager:
+
+ META_NETWORK_KEY = "um_network_key"
+
+ MANUAL_DEVICES_PREFERENCE_KEY = "um3networkprinting/manual_instances"
+ MIN_SUPPORTED_CLUSTER_VERSION = Version("4.0.0")
+
+ # The translation catalog for this device.
+ I18N_CATALOG = i18nCatalog("cura")
+
+ # Signal emitted when the list of discovered devices changed.
+ discoveredDevicesChanged = Signal()
+
+ def __init__(self) -> None:
+
+ # Persistent dict containing the networked clusters.
+ self._discovered_devices = {} # type: Dict[str, LocalClusterOutputDevice]
+ self._output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+
+ # Hook up ZeroConf client.
+ self._zero_conf_client = ZeroConfClient()
+ self._zero_conf_client.addedNetworkCluster.connect(self._onDeviceDiscovered)
+ self._zero_conf_client.removedNetworkCluster.connect(self._onDiscoveredDeviceRemoved)
+
+ ## Start the network discovery.
+ def start(self) -> None:
+ self._zero_conf_client.start()
+ for address in self._getStoredManualAddresses():
+ self.addManualDevice(address)
+
+ ## Stop network discovery and clean up discovered devices.
+ def stop(self) -> None:
+ self._zero_conf_client.stop()
+ for instance_name in list(self._discovered_devices):
+ self._onDiscoveredDeviceRemoved(instance_name)
+
+ ## Restart discovery on the local network.
+ def startDiscovery(self):
+ self.stop()
+ self.start()
+
+ ## Add a networked printer manually by address.
+ def addManualDevice(self, address: str, callback: Optional[Callable[[bool, str], None]] = None) -> None:
+ api_client = ClusterApiClient(address, lambda error: Logger.log("e", str(error)))
+ api_client.getSystem(lambda status: self._onCheckManualDeviceResponse(address, status, callback))
+
+ ## Remove a manually added networked printer.
+ def removeManualDevice(self, device_id: str, address: Optional[str] = None) -> None:
+ if device_id not in self._discovered_devices and address is not None:
+ device_id = "manual:{}".format(address)
+
+ if device_id in self._discovered_devices:
+ address = address or self._discovered_devices[device_id].ipAddress
+ self._onDiscoveredDeviceRemoved(device_id)
+
+ if address in self._getStoredManualAddresses():
+ self._removeStoredManualAddress(address)
+
+ ## Force reset all network device connections.
+ def refreshConnections(self) -> None:
+ self._connectToActiveMachine()
+
+ ## Get the discovered devices.
+ def getDiscoveredDevices(self) -> Dict[str, LocalClusterOutputDevice]:
+ return self._discovered_devices
+
+ ## Connect the active machine to a given device.
+ def associateActiveMachineWithPrinterDevice(self, device: LocalClusterOutputDevice) -> None:
+ active_machine = CuraApplication.getInstance().getGlobalContainerStack()
+ if not active_machine:
+ return
+ self._connectToOutputDevice(device, active_machine)
+ self._connectToActiveMachine()
+
+ # Pre-select the correct machine type of the group host.
+ # We first need to find the correct definition because the machine manager only takes name as input, not ID.
+ definitions = CuraApplication.getInstance().getContainerRegistry().findContainers(id = device.printerType)
+ if not definitions:
+ return
+ CuraApplication.getInstance().getMachineManager().switchPrinterType(definitions[0].getName())
+
+ ## Callback for when the active machine was changed by the user or a new remote cluster was found.
+ def _connectToActiveMachine(self) -> None:
+ active_machine = CuraApplication.getInstance().getGlobalContainerStack()
+ if not active_machine:
+ return
+
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+ stored_device_id = active_machine.getMetaDataEntry(self.META_NETWORK_KEY)
+ for device in self._discovered_devices.values():
+ if device.key == stored_device_id:
+ # Connect to it if the stored key matches.
+ self._connectToOutputDevice(device, active_machine)
+ elif device.key in output_device_manager.getOutputDeviceIds():
+ # Remove device if it is not meant for the active machine.
+ output_device_manager.removeOutputDevice(device.key)
+
+ ## Callback for when a manual device check request was responded to.
+ def _onCheckManualDeviceResponse(self, address: str, status: PrinterSystemStatus,
+ callback: Optional[Callable[[bool, str], None]] = None) -> None:
+ self._onDeviceDiscovered("manual:{}".format(address), address, {
+ b"name": status.name.encode("utf-8"),
+ b"address": address.encode("utf-8"),
+ b"machine": str(status.hardware.get("typeid", "")).encode("utf-8"),
+ b"manual": b"true",
+ b"firmware_version": status.firmware.encode("utf-8"),
+ b"cluster_size": b"1"
+ })
+ self._storeManualAddress(address)
+ if callback is not None:
+ CuraApplication.getInstance().callLater(callback, True, address)
+
+ ## Returns a dict of printer BOM numbers to machine types.
+ # These numbers are available in the machine definition already so we just search for them here.
+ @staticmethod
+ def _getPrinterTypeIdentifiers() -> Dict[str, str]:
+ container_registry = CuraApplication.getInstance().getContainerRegistry()
+ ultimaker_machines = container_registry.findContainersMetadata(type="machine", manufacturer="Ultimaker B.V.")
+ found_machine_type_identifiers = {} # type: Dict[str, str]
+ for machine in ultimaker_machines:
+ machine_type = machine.get("id", None)
+ machine_bom_numbers = machine.get("bom_numbers", [])
+ if machine_type and machine_bom_numbers:
+ for bom_number in machine_bom_numbers:
+ # This produces a n:1 mapping of bom numbers to machine types
+ # allowing the S5R1 and S5R2 hardware to use a single S5 definition.
+ found_machine_type_identifiers[str(bom_number)] = machine_type
+ return found_machine_type_identifiers
+
+ ## Add a new device.
+ def _onDeviceDiscovered(self, key: str, address: str, properties: Dict[bytes, bytes]) -> None:
+ machine_identifier = properties.get(b"machine", b"").decode("utf-8")
+ printer_type_identifiers = self._getPrinterTypeIdentifiers()
+
+ # Detect the machine type based on the BOM number that is sent over the network.
+ properties[b"printer_type"] = b"Unknown"
+ for bom, p_type in printer_type_identifiers.items():
+ if machine_identifier.startswith(bom):
+ properties[b"printer_type"] = bytes(p_type, encoding="utf8")
+ break
+
+ device = LocalClusterOutputDevice(key, address, properties)
+ discovered_printers_model = CuraApplication.getInstance().getDiscoveredPrintersModel()
+ if address in list(discovered_printers_model.discoveredPrintersByAddress.keys()):
+ # The printer was already added, we just update the available data.
+ discovered_printers_model.updateDiscoveredPrinter(
+ ip_address=address,
+ name=device.getName(),
+ machine_type=device.printerType
+ )
+ else:
+ # The printer was not added yet so let's do that.
+ discovered_printers_model.addDiscoveredPrinter(
+ ip_address=address,
+ key=device.getId(),
+ name=device.getName(),
+ create_callback=self._createMachineFromDiscoveredDevice,
+ machine_type=device.printerType,
+ device=device
+ )
+ self._discovered_devices[device.getId()] = device
+ self.discoveredDevicesChanged.emit()
+ self._connectToActiveMachine()
+
+ ## Remove a device.
+ def _onDiscoveredDeviceRemoved(self, device_id: str) -> None:
+ device = self._discovered_devices.pop(device_id, None) # type: Optional[LocalClusterOutputDevice]
+ if not device:
+ return
+ device.close()
+ CuraApplication.getInstance().getDiscoveredPrintersModel().removeDiscoveredPrinter(device.address)
+ self.discoveredDevicesChanged.emit()
+
+ ## Create a machine instance based on the discovered network printer.
+ def _createMachineFromDiscoveredDevice(self, device_id: str) -> None:
+ device = self._discovered_devices.get(device_id)
+ if device is None:
+ return
+
+ # Create a new machine and activate it.
+ # We do not use use MachineManager.addMachine here because we need to set the network key before activating it.
+ # If we do not do this the auto-pairing with the cloud-equivalent device will not work.
+ new_machine = CuraStackBuilder.createMachine(device.name, device.printerType)
+ if not new_machine:
+ Logger.log("e", "Failed creating a new machine")
+ return
+ new_machine.setMetaDataEntry(self.META_NETWORK_KEY, device.key)
+ CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId())
+ self._connectToOutputDevice(device, new_machine)
+ self._showCloudFlowMessage(device)
+
+ ## Add an address to the stored preferences.
+ def _storeManualAddress(self, address: str) -> None:
+ stored_addresses = self._getStoredManualAddresses()
+ if address in stored_addresses:
+ return # Prevent duplicates.
+ stored_addresses.append(address)
+ new_value = ",".join(stored_addresses)
+ CuraApplication.getInstance().getPreferences().setValue(self.MANUAL_DEVICES_PREFERENCE_KEY, new_value)
+
+ ## Remove an address from the stored preferences.
+ def _removeStoredManualAddress(self, address: str) -> None:
+ stored_addresses = self._getStoredManualAddresses()
+ try:
+ stored_addresses.remove(address) # Can throw a ValueError
+ new_value = ",".join(stored_addresses)
+ CuraApplication.getInstance().getPreferences().setValue(self.MANUAL_DEVICES_PREFERENCE_KEY, new_value)
+ except ValueError:
+ Logger.log("w", "Could not remove address from stored_addresses, it was not there")
+
+ ## Load the user-configured manual devices from Cura preferences.
+ def _getStoredManualAddresses(self) -> List[str]:
+ preferences = CuraApplication.getInstance().getPreferences()
+ preferences.addPreference(self.MANUAL_DEVICES_PREFERENCE_KEY, "")
+ manual_instances = preferences.getValue(self.MANUAL_DEVICES_PREFERENCE_KEY).split(",")
+ return manual_instances
+
+ ## Add a device to the current active machine.
+ def _connectToOutputDevice(self, device: UltimakerNetworkedPrinterOutputDevice, machine: GlobalStack) -> None:
+
+ # Make sure users know that we no longer support legacy devices.
+ if Version(device.firmwareVersion) < self.MIN_SUPPORTED_CLUSTER_VERSION:
+ LegacyDeviceNoLongerSupportedMessage().show()
+ return
+
+ machine.setName(device.name)
+ machine.setMetaDataEntry(self.META_NETWORK_KEY, device.key)
+ machine.setMetaDataEntry("group_name", device.name)
+ machine.addConfiguredConnectionType(device.connectionType.value)
+
+ if not device.isConnected():
+ device.connect()
+
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+ if device.key not in output_device_manager.getOutputDeviceIds():
+ output_device_manager.addOutputDevice(device)
+
+ ## Nudge the user to start using Ultimaker Cloud.
+ @staticmethod
+ def _showCloudFlowMessage(device: LocalClusterOutputDevice) -> None:
+ if CuraApplication.getInstance().getMachineManager().activeMachineIsUsingCloudConnection:
+ # This printer is already cloud connected, so we do not bother the user anymore.
+ return
+ if not CuraApplication.getInstance().getCuraAPI().account.isLoggedIn:
+ # Do not show the message if the user is not signed in.
+ return
+ CloudFlowMessage(device.ipAddress).show()
diff --git a/plugins/UM3NetworkPrinting/src/SendMaterialJob.py b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py
similarity index 59%
rename from plugins/UM3NetworkPrinting/src/SendMaterialJob.py
rename to plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py
index f0fde818c4..09949ed37e 100644
--- a/plugins/UM3NetworkPrinting/src/SendMaterialJob.py
+++ b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py
@@ -1,20 +1,20 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-
-import json
import os
-from typing import Dict, TYPE_CHECKING, Set, Optional
+from typing import Dict, TYPE_CHECKING, Set, List
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
from UM.Job import Job
from UM.Logger import Logger
+from UM.Settings import ContainerRegistry
from cura.CuraApplication import CuraApplication
-# Absolute imports don't work in plugins
-from .Models import ClusterMaterial, LocalMaterial
+from ..Models.Http.ClusterMaterial import ClusterMaterial
+from ..Models.LocalMaterial import LocalMaterial
+from ..Messages.MaterialSyncMessage import MaterialSyncMessage
if TYPE_CHECKING:
- from .ClusterUM3OutputDevice import ClusterUM3OutputDevice
+ from .LocalClusterOutputDevice import LocalClusterOutputDevice
## Asynchronous job to send material profiles to the printer.
@@ -22,75 +22,56 @@ if TYPE_CHECKING:
# This way it won't freeze up the interface while sending those materials.
class SendMaterialJob(Job):
- def __init__(self, device: "ClusterUM3OutputDevice") -> None:
+ def __init__(self, device: "LocalClusterOutputDevice") -> None:
super().__init__()
- self.device = device # type: ClusterUM3OutputDevice
+ self.device = device # type: LocalClusterOutputDevice
## Send the request to the printer and register a callback
def run(self) -> None:
- self.device.get("materials/", on_finished = self._onGetRemoteMaterials)
+ self.device.getMaterials(on_finished = self._onGetMaterials)
- ## Process the materials reply from the printer.
- #
- # \param reply The reply from the printer, a json file.
- def _onGetRemoteMaterials(self, reply: QNetworkReply) -> None:
- # Got an error from the HTTP request. If we did not receive a 200 something happened.
- if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
- Logger.log("e", "Error fetching materials from printer: %s", reply.errorString())
- return
-
- # Collect materials from the printer's reply and send the missing ones if needed.
- remote_materials_by_guid = self._parseReply(reply)
- if remote_materials_by_guid:
- self._sendMissingMaterials(remote_materials_by_guid)
+ ## Callback for when the remote materials were returned.
+ def _onGetMaterials(self, materials: List[ClusterMaterial]) -> None:
+ remote_materials_by_guid = {material.guid: material for material in materials}
+ self._sendMissingMaterials(remote_materials_by_guid)
## Determine which materials should be updated and send them to the printer.
- #
# \param remote_materials_by_guid The remote materials by GUID.
def _sendMissingMaterials(self, remote_materials_by_guid: Dict[str, ClusterMaterial]) -> None:
- # Collect local materials
local_materials_by_guid = self._getLocalMaterials()
if len(local_materials_by_guid) == 0:
Logger.log("d", "There are no local materials to synchronize with the printer.")
return
-
- # Find out what materials are new or updated and must be sent to the printer
material_ids_to_send = self._determineMaterialsToSend(local_materials_by_guid, remote_materials_by_guid)
if len(material_ids_to_send) == 0:
Logger.log("d", "There are no remote materials to update.")
return
-
- # Send materials to the printer
self._sendMaterials(material_ids_to_send)
## From the local and remote materials, determine which ones should be synchronized.
- #
# Makes a Set of id's containing only the id's of the materials that are not on the printer yet or the ones that
# are newer in Cura.
- #
# \param local_materials The local materials by GUID.
# \param remote_materials The remote materials by GUID.
@staticmethod
def _determineMaterialsToSend(local_materials: Dict[str, LocalMaterial],
remote_materials: Dict[str, ClusterMaterial]) -> Set[str]:
return {
- material.id
- for guid, material in local_materials.items()
- if guid not in remote_materials or material.version > remote_materials[guid].version
+ local_material.id
+ for guid, local_material in local_materials.items()
+ if guid not in remote_materials.keys() or local_material.version > remote_materials[guid].version
}
## Send the materials to the printer.
- #
# The given materials will be loaded from disk en sent to to printer.
# The given id's will be matched with filenames of the locally stored materials.
- #
# \param materials_to_send A set with id's of materials that must be sent.
def _sendMaterials(self, materials_to_send: Set[str]) -> None:
container_registry = CuraApplication.getInstance().getContainerRegistry()
- material_manager = CuraApplication.getInstance().getMaterialManager()
- material_group_dict = material_manager.getAllMaterialGroups()
+ all_materials = container_registry.findInstanceContainersMetadata(type = "material")
+ all_base_files = {material["base_file"] for material in all_materials if "base_file" in material} # Filters out uniques by making it a set. Don't include files without base file (i.e. empty material).
- for root_material_id in material_group_dict:
+ for root_material_id in all_base_files:
if root_material_id not in materials_to_send:
# If the material does not have to be sent we skip it.
continue
@@ -104,9 +85,7 @@ class SendMaterialJob(Job):
self._sendMaterialFile(file_path, file_name, root_material_id)
## Send a single material file to the printer.
- #
# Also add the material signature file if that is available.
- #
# \param file_path The path of the material file.
# \param file_name The name of the material file.
# \param material_id The ID of the material in the file.
@@ -126,61 +105,41 @@ class SendMaterialJob(Job):
parts.append(self.device.createFormPart("name=\"signature_file\"; filename=\"{file_name}\""
.format(file_name = signature_file_name), f.read()))
- Logger.log("d", "Syncing material {material_id} with cluster.".format(material_id = material_id))
- self.device.postFormWithParts(target = "materials/", parts = parts, on_finished = self.sendingFinished)
+ # FIXME: move form posting to API client
+ self.device.postFormWithParts(target = "/cluster-api/v1/materials/", parts = parts,
+ on_finished = self._sendingFinished)
## Check a reply from an upload to the printer and log an error when the call failed
- @staticmethod
- def sendingFinished(reply: QNetworkReply) -> None:
+ def _sendingFinished(self, reply: QNetworkReply) -> None:
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
- Logger.log("e", "Received error code from printer when syncing material: {code}, {text}".format(
- code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute),
- text = reply.errorString()
- ))
-
- ## Parse the reply from the printer
- #
- # Parses the reply to a "/materials" request to the printer
- #
- # \return a dictionary of ClusterMaterial objects by GUID
- # \throw KeyError Raised when on of the materials does not include a valid guid
- @classmethod
- def _parseReply(cls, reply: QNetworkReply) -> Optional[Dict[str, ClusterMaterial]]:
- try:
- remote_materials = json.loads(reply.readAll().data().decode("utf-8"))
- return {material["guid"]: ClusterMaterial(**material) for material in remote_materials}
- except UnicodeDecodeError:
- Logger.log("e", "Request material storage on printer: I didn't understand the printer's answer.")
- except json.JSONDecodeError:
- Logger.log("e", "Request material storage on printer: I didn't understand the printer's answer.")
- except ValueError:
- Logger.log("e", "Request material storage on printer: Printer's answer had an incorrect value.")
- except TypeError:
- Logger.log("e", "Request material storage on printer: Printer's answer was missing a required value.")
- return None
+ Logger.log("w", "Error while syncing material: %s", reply.errorString())
+ return
+ body = reply.readAll().data().decode('utf8')
+ if "not added" in body:
+ # For some reason the cluster returns a 200 sometimes even when syncing failed.
+ return
+ # Inform the user that materials have been synced. This message only shows itself when not already visible.
+ # Because of the guards above it is not shown when syncing failed (which is not always an actual problem).
+ MaterialSyncMessage(self.device).show()
## Retrieves a list of local materials
- #
# Only the new newest version of the local materials is returned
- #
# \return a dictionary of LocalMaterial objects by GUID
- def _getLocalMaterials(self) -> Dict[str, LocalMaterial]:
+ @staticmethod
+ def _getLocalMaterials() -> Dict[str, LocalMaterial]:
result = {} # type: Dict[str, LocalMaterial]
- material_manager = CuraApplication.getInstance().getMaterialManager()
-
- material_group_dict = material_manager.getAllMaterialGroups()
+ all_materials = CuraApplication.getInstance().getContainerRegistry().findInstanceContainersMetadata(type = "material")
+ all_base_files = [material for material in all_materials if material["id"] == material.get("base_file")] # Don't send materials without base_file: The empty material doesn't need to be sent.
# Find the latest version of all material containers in the registry.
- for root_material_id, material_group in material_group_dict.items():
- material_metadata = material_group.root_material_node.getMetadata()
-
+ for material_metadata in all_base_files:
try:
# material version must be an int
material_metadata["version"] = int(material_metadata["version"])
# Create a new local material
local_material = LocalMaterial(**material_metadata)
- local_material.id = root_material_id
+ local_material.id = material_metadata["id"]
if local_material.GUID not in result or \
local_material.GUID not in result or \
diff --git a/plugins/UM3NetworkPrinting/src/Network/ZeroConfClient.py b/plugins/UM3NetworkPrinting/src/Network/ZeroConfClient.py
new file mode 100644
index 0000000000..421246fb95
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Network/ZeroConfClient.py
@@ -0,0 +1,146 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from queue import Queue
+from threading import Thread, Event
+from time import time
+from typing import Optional
+
+from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
+
+from UM.Logger import Logger
+from UM.Signal import Signal
+from cura.CuraApplication import CuraApplication
+
+
+## The ZeroConfClient handles all network discovery logic.
+# It emits signals when new network services were found or disappeared.
+class ZeroConfClient:
+
+ # The discovery protocol name for Ultimaker printers.
+ ZERO_CONF_NAME = u"_ultimaker._tcp.local."
+
+ # Signals emitted when new services were discovered or removed on the network.
+ addedNetworkCluster = Signal()
+ removedNetworkCluster = Signal()
+
+ def __init__(self) -> None:
+ self._zero_conf = None # type: Optional[Zeroconf]
+ self._zero_conf_browser = None # type: Optional[ServiceBrowser]
+ self._service_changed_request_queue = None # type: Optional[Queue]
+ self._service_changed_request_event = None # type: Optional[Event]
+ self._service_changed_request_thread = None # type: Optional[Thread]
+
+ ## The ZeroConf service changed requests are handled in a separate thread so we don't block the UI.
+ # We can also re-schedule the requests when they fail to get detailed service info.
+ # Any new or re-reschedule requests will be appended to the request queue and the thread will process them.
+ def start(self) -> None:
+ self._service_changed_request_queue = Queue()
+ self._service_changed_request_event = Event()
+ try:
+ self._zero_conf = Zeroconf()
+ # CURA-6855 catch WinErrors
+ except OSError:
+ Logger.logException("e", "Failed to create zeroconf instance.")
+ return
+
+ self._service_changed_request_thread = Thread(target = self._handleOnServiceChangedRequests, daemon = True, name = "ZeroConfServiceChangedThread")
+ self._service_changed_request_thread.start()
+ self._zero_conf_browser = ServiceBrowser(self._zero_conf, self.ZERO_CONF_NAME, [self._queueService])
+
+ # Cleanup ZeroConf resources.
+ def stop(self) -> None:
+ if self._zero_conf is not None:
+ self._zero_conf.close()
+ self._zero_conf = None
+ if self._zero_conf_browser is not None:
+ self._zero_conf_browser.cancel()
+ self._zero_conf_browser = None
+
+ ## Handles a change is discovered network services.
+ def _queueService(self, zeroconf: Zeroconf, service_type, name: str, state_change: ServiceStateChange) -> None:
+ item = (zeroconf, service_type, name, state_change)
+ if not self._service_changed_request_queue or not self._service_changed_request_event:
+ return
+ self._service_changed_request_queue.put(item)
+ self._service_changed_request_event.set()
+
+ ## Callback for when a ZeroConf service has changes.
+ def _handleOnServiceChangedRequests(self) -> None:
+ if not self._service_changed_request_queue or not self._service_changed_request_event:
+ return
+
+ while True:
+ # Wait for the event to be set
+ self._service_changed_request_event.wait(timeout=5.0)
+
+ # Stop if the application is shutting down
+ if CuraApplication.getInstance().isShuttingDown():
+ return
+
+ self._service_changed_request_event.clear()
+
+ # Handle all pending requests
+ reschedule_requests = [] # A list of requests that have failed so later they will get re-scheduled
+ while not self._service_changed_request_queue.empty():
+ request = self._service_changed_request_queue.get()
+ zeroconf, service_type, name, state_change = request
+ try:
+ result = self._onServiceChanged(zeroconf, service_type, name, state_change)
+ if not result:
+ reschedule_requests.append(request)
+ except Exception:
+ Logger.logException("e", "Failed to get service info for [%s] [%s], the request will be rescheduled",
+ service_type, name)
+ reschedule_requests.append(request)
+
+ # Re-schedule the failed requests if any
+ if reschedule_requests:
+ for request in reschedule_requests:
+ self._service_changed_request_queue.put(request)
+
+ ## Handler for zeroConf detection.
+ # Return True or False indicating if the process succeeded.
+ # Note that this function can take over 3 seconds to complete. Be careful calling it from the main thread.
+ def _onServiceChanged(self, zero_conf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange
+ ) -> bool:
+ if state_change == ServiceStateChange.Added:
+ return self._onServiceAdded(zero_conf, service_type, name)
+ elif state_change == ServiceStateChange.Removed:
+ return self._onServiceRemoved(name)
+ return True
+
+ ## Handler for when a ZeroConf service was added.
+ def _onServiceAdded(self, zero_conf: Zeroconf, service_type: str, name: str) -> bool:
+ # First try getting info from zero-conf cache
+ info = ServiceInfo(service_type, name, properties={})
+ for record in zero_conf.cache.entries_with_name(name.lower()):
+ info.update_record(zero_conf, time(), record)
+
+ for record in zero_conf.cache.entries_with_name(info.server):
+ info.update_record(zero_conf, time(), record)
+ if info.address:
+ break
+
+ # Request more data if info is not complete
+ if not info.address:
+ info = zero_conf.get_service_info(service_type, name)
+
+ if info:
+ type_of_device = info.properties.get(b"type", None)
+ if type_of_device:
+ if type_of_device == b"printer":
+ address = '.'.join(map(lambda n: str(n), info.address))
+ self.addedNetworkCluster.emit(str(name), address, info.properties)
+ else:
+ Logger.log("w", "The type of the found device is '%s', not 'printer'." % type_of_device)
+ else:
+ Logger.log("w", "Could not get information about %s" % name)
+ return False
+
+ return True
+
+ ## Handler for when a ZeroConf service was removed.
+ def _onServiceRemoved(self, name: str) -> bool:
+ Logger.log("d", "ZeroConf service removed: %s" % name)
+ self.removedNetworkCluster.emit(str(name))
+ return True
diff --git a/plugins/UM3NetworkPrinting/src/Network/__init__.py b/plugins/UM3NetworkPrinting/src/Network/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py
index 3fce903b1a..3ab37297b5 100644
--- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py
+++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py
@@ -1,533 +1,73 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import json
-from queue import Queue
-from threading import Event, Thread
-from time import time
-import os
-
-from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
-from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
-from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
-from PyQt5.QtGui import QDesktopServices
+from typing import Optional, Callable, Dict
+from UM.Signal import Signal
from cura.CuraApplication import CuraApplication
-from cura.PrinterOutputDevice import ConnectionType
-from cura.Settings.GlobalStack import GlobalStack # typing
-from UM.i18n import i18nCatalog
-from UM.Logger import Logger
-from UM.Message import Message
+from UM.OutputDevice.OutputDeviceManager import ManualDeviceAdditionAttempt
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
-from UM.PluginRegistry import PluginRegistry
-from UM.Signal import Signal, signalemitter
-from UM.Version import Version
-from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice
+from .Network.LocalClusterOutputDevice import LocalClusterOutputDevice
+from .Network.LocalClusterOutputDeviceManager import LocalClusterOutputDeviceManager
from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
-from typing import Optional
-i18n_catalog = i18nCatalog("cura")
-
-## This plugin handles the connection detection & creation of output device objects for the UM3 printer.
-# Zero-Conf is used to detect printers, which are saved in a dict.
-# If we discover a printer that has the same key as the active machine instance a connection is made.
-@signalemitter
+## This plugin handles the discovery and networking for Ultimaker 3D printers that support network and cloud printing.
class UM3OutputDevicePlugin(OutputDevicePlugin):
- addDeviceSignal = Signal()
- removeDeviceSignal = Signal()
+
+ # Signal emitted when the list of discovered devices changed. Used by printer action in this plugin.
discoveredDevicesChanged = Signal()
- cloudFlowIsPossible = Signal()
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
-
- self._zero_conf = None
- self._zero_conf_browser = None
- self._application = CuraApplication.getInstance()
+ # Create a network output device manager that abstracts all network connection logic away.
+ self._network_output_device_manager = LocalClusterOutputDeviceManager()
+ self._network_output_device_manager.discoveredDevicesChanged.connect(self.discoveredDevicesChanged)
# Create a cloud output device manager that abstracts all cloud connection logic away.
self._cloud_output_device_manager = CloudOutputDeviceManager()
- # Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
- self.addDeviceSignal.connect(self._onAddDevice)
- self.removeDeviceSignal.connect(self._onRemoveDevice)
+ # Refresh network connections when another machine was selected in Cura.
+ # This ensures no output devices are still connected that do not belong to the new active machine.
+ CuraApplication.getInstance().globalContainerStackChanged.connect(self.refreshConnections)
- self._application.globalContainerStackChanged.connect(self.reCheckConnections)
-
- self._discovered_devices = {}
-
- self._network_manager = QNetworkAccessManager()
- self._network_manager.finished.connect(self._onNetworkRequestFinished)
-
- self._min_cluster_version = Version("4.0.0")
- self._min_cloud_version = Version("5.2.0")
-
- self._api_version = "1"
- self._api_prefix = "/api/v" + self._api_version + "/"
- self._cluster_api_version = "1"
- self._cluster_api_prefix = "/cluster-api/v" + self._cluster_api_version + "/"
-
- # Get list of manual instances from preferences
- self._preferences = CuraApplication.getInstance().getPreferences()
- self._preferences.addPreference("um3networkprinting/manual_instances",
- "") # A comma-separated list of ip adresses or hostnames
-
- self._manual_instances = self._preferences.getValue("um3networkprinting/manual_instances").split(",")
-
- # Store the last manual entry key
- self._last_manual_entry_key = "" # type: str
-
- # The zero-conf service changed requests are handled in a separate thread, so we can re-schedule the requests
- # which fail to get detailed service info.
- # Any new or re-scheduled requests will be appended to the request queue, and the handling thread will pick
- # them up and process them.
- self._service_changed_request_queue = Queue()
- self._service_changed_request_event = Event()
- self._service_changed_request_thread = Thread(target=self._handleOnServiceChangedRequests, daemon=True)
- self._service_changed_request_thread.start()
-
- self._account = self._application.getCuraAPI().account
-
- # Check if cloud flow is possible when user logs in
- self._account.loginStateChanged.connect(self.checkCloudFlowIsPossible)
-
- # Check if cloud flow is possible when user switches machines
- self._application.globalContainerStackChanged.connect(self._onMachineSwitched)
-
- # Listen for when cloud flow is possible
- self.cloudFlowIsPossible.connect(self._onCloudFlowPossible)
-
- # Listen if cloud cluster was added
- self._cloud_output_device_manager.addedCloudCluster.connect(self._onCloudPrintingConfigured)
-
- # Listen if cloud cluster was removed
- self._cloud_output_device_manager.removedCloudCluster.connect(self.checkCloudFlowIsPossible)
-
- self._start_cloud_flow_message = None # type: Optional[Message]
- self._cloud_flow_complete_message = None # type: Optional[Message]
-
- def getDiscoveredDevices(self):
- return self._discovered_devices
-
- def getLastManualDevice(self) -> str:
- return self._last_manual_entry_key
-
- def resetLastManualDevice(self) -> None:
- self._last_manual_entry_key = ""
-
- ## Start looking for devices on network.
+ ## Start looking for devices in the network and cloud.
def start(self):
- self.startDiscovery()
+ self._network_output_device_manager.start()
self._cloud_output_device_manager.start()
- def startDiscovery(self):
- self.stop()
- if self._zero_conf_browser:
- self._zero_conf_browser.cancel()
- self._zero_conf_browser = None # Force the old ServiceBrowser to be destroyed.
-
- for instance_name in list(self._discovered_devices):
- self._onRemoveDevice(instance_name)
-
- self._zero_conf = Zeroconf()
- self._zero_conf_browser = ServiceBrowser(self._zero_conf, u'_ultimaker._tcp.local.',
- [self._appendServiceChangedRequest])
-
- # Look for manual instances from preference
- for address in self._manual_instances:
- if address:
- self.addManualDevice(address)
- self.resetLastManualDevice()
-
- def reCheckConnections(self):
- active_machine = CuraApplication.getInstance().getGlobalContainerStack()
- if not active_machine:
- return
-
- um_network_key = active_machine.getMetaDataEntry("um_network_key")
-
- for key in self._discovered_devices:
- if key == um_network_key:
- if not self._discovered_devices[key].isConnected():
- Logger.log("d", "Attempting to connect with [%s]" % key)
- # It should already be set, but if it actually connects we know for sure it's supported!
- active_machine.addConfiguredConnectionType(self._discovered_devices[key].connectionType.value)
- self._discovered_devices[key].connect()
- self._discovered_devices[key].connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
- else:
- self._onDeviceConnectionStateChanged(key)
- else:
- if self._discovered_devices[key].isConnected():
- Logger.log("d", "Attempting to close connection with [%s]" % key)
- self._discovered_devices[key].close()
- self._discovered_devices[key].connectionStateChanged.disconnect(self._onDeviceConnectionStateChanged)
-
- def _onDeviceConnectionStateChanged(self, key):
- if key not in self._discovered_devices:
- return
- if self._discovered_devices[key].isConnected():
- # Sometimes the status changes after changing the global container and maybe the device doesn't belong to this machine
- um_network_key = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key")
- if key == um_network_key:
- self.getOutputDeviceManager().addOutputDevice(self._discovered_devices[key])
- self.checkCloudFlowIsPossible()
- else:
- self.getOutputDeviceManager().removeOutputDevice(key)
-
- def stop(self):
- if self._zero_conf is not None:
- Logger.log("d", "zeroconf close...")
- self._zero_conf.close()
+ # Stop network and cloud discovery.
+ def stop(self) -> None:
+ self._network_output_device_manager.stop()
self._cloud_output_device_manager.stop()
- def removeManualDevice(self, key, address = None):
- if key in self._discovered_devices:
- if not address:
- address = self._discovered_devices[key].ipAddress
- self._onRemoveDevice(key)
- self.resetLastManualDevice()
+ ## Restart network discovery.
+ def startDiscovery(self) -> None:
+ self._network_output_device_manager.startDiscovery()
- if address in self._manual_instances:
- self._manual_instances.remove(address)
- self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances))
+ ## Force refreshing the network connections.
+ def refreshConnections(self) -> None:
+ self._network_output_device_manager.refreshConnections()
+ self._cloud_output_device_manager.refreshConnections()
- def addManualDevice(self, address):
- if address not in self._manual_instances:
- self._manual_instances.append(address)
- self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances))
+ ## Indicate that this plugin supports adding networked printers manually.
+ def canAddManualDevice(self, address: str = "") -> ManualDeviceAdditionAttempt:
+ return ManualDeviceAdditionAttempt.PRIORITY
- instance_name = "manual:%s" % address
- properties = {
- b"name": address.encode("utf-8"),
- b"address": address.encode("utf-8"),
- b"manual": b"true",
- b"incomplete": b"true",
- b"temporary": b"true" # Still a temporary device until all the info is retrieved in _onNetworkRequestFinished
- }
+ ## Add a networked printer manually based on its network address.
+ def addManualDevice(self, address: str, callback: Optional[Callable[[bool, str], None]] = None) -> None:
+ self._network_output_device_manager.addManualDevice(address, callback)
- if instance_name not in self._discovered_devices:
- # Add a preliminary printer instance
- self._onAddDevice(instance_name, address, properties)
- self._last_manual_entry_key = instance_name
-
- self._checkManualDevice(address)
-
- def _checkManualDevice(self, address):
- # Check if a UM3 family device exists at this address.
- # If a printer responds, it will replace the preliminary printer created above
- # origin=manual is for tracking back the origin of the call
- url = QUrl("http://" + address + self._api_prefix + "system")
- name_request = QNetworkRequest(url)
- self._network_manager.get(name_request)
-
- def _onNetworkRequestFinished(self, reply):
- reply_url = reply.url().toString()
-
- if "system" in reply_url:
- if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
- # Something went wrong with checking the firmware version!
- return
-
- try:
- system_info = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except:
- Logger.log("e", "Something went wrong converting the JSON.")
- return
-
- address = reply.url().host()
- has_cluster_capable_firmware = Version(system_info["firmware"]) > self._min_cluster_version
- instance_name = "manual:%s" % address
- properties = {
- b"name": (system_info["name"] + " (manual)").encode("utf-8"),
- b"address": address.encode("utf-8"),
- b"firmware_version": system_info["firmware"].encode("utf-8"),
- b"manual": b"true",
- b"machine": str(system_info['hardware']["typeid"]).encode("utf-8")
- }
-
- if has_cluster_capable_firmware:
- # Cluster needs an additional request, before it's completed.
- properties[b"incomplete"] = b"true"
-
- # Check if the device is still in the list & re-add it with the updated
- # information.
- if instance_name in self._discovered_devices:
- self._onRemoveDevice(instance_name)
- self._onAddDevice(instance_name, address, properties)
-
- if has_cluster_capable_firmware:
- # We need to request more info in order to figure out the size of the cluster.
- cluster_url = QUrl("http://" + address + self._cluster_api_prefix + "printers/")
- cluster_request = QNetworkRequest(cluster_url)
- self._network_manager.get(cluster_request)
-
- elif "printers" in reply_url:
- if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
- # Something went wrong with checking the amount of printers the cluster has!
- return
- # So we confirmed that the device is in fact a cluster printer, and we should now know how big it is.
- try:
- cluster_printers_list = json.loads(bytes(reply.readAll()).decode("utf-8"))
- except:
- Logger.log("e", "Something went wrong converting the JSON.")
- return
- address = reply.url().host()
- instance_name = "manual:%s" % address
- if instance_name in self._discovered_devices:
- device = self._discovered_devices[instance_name]
- properties = device.getProperties().copy()
- if b"incomplete" in properties:
- del properties[b"incomplete"]
- properties[b"cluster_size"] = len(cluster_printers_list)
- self._onRemoveDevice(instance_name)
- self._onAddDevice(instance_name, address, properties)
-
- def _onRemoveDevice(self, device_id):
- device = self._discovered_devices.pop(device_id, None)
- if device:
- if device.isConnected():
- device.disconnect()
- try:
- device.connectionStateChanged.disconnect(self._onDeviceConnectionStateChanged)
- except TypeError:
- # Disconnect already happened.
- pass
-
- self.discoveredDevicesChanged.emit()
-
- def _onAddDevice(self, name, address, properties):
- # Check what kind of device we need to add; Depending on the firmware we either add a "Connect"/"Cluster"
- # or "Legacy" UM3 device.
- cluster_size = int(properties.get(b"cluster_size", -1))
-
- printer_type = properties.get(b"machine", b"").decode("utf-8")
- printer_type_identifiers = {
- "9066": "ultimaker3",
- "9511": "ultimaker3_extended",
- "9051": "ultimaker_s5"
- }
-
- for key, value in printer_type_identifiers.items():
- if printer_type.startswith(key):
- properties[b"printer_type"] = bytes(value, encoding="utf8")
- break
- else:
- properties[b"printer_type"] = b"Unknown"
- if cluster_size >= 0:
- device = ClusterUM3OutputDevice.ClusterUM3OutputDevice(name, address, properties)
- else:
- device = LegacyUM3OutputDevice.LegacyUM3OutputDevice(name, address, properties)
-
- self._discovered_devices[device.getId()] = device
- self.discoveredDevicesChanged.emit()
-
- global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
- if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"):
- # Ensure that the configured connection type is set.
- global_container_stack.addConfiguredConnectionType(device.connectionType.value)
- device.connect()
- device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
-
- ## Appends a service changed request so later the handling thread will pick it up and processes it.
- def _appendServiceChangedRequest(self, zeroconf, service_type, name, state_change):
- # append the request and set the event so the event handling thread can pick it up
- item = (zeroconf, service_type, name, state_change)
- self._service_changed_request_queue.put(item)
- self._service_changed_request_event.set()
-
- def _handleOnServiceChangedRequests(self):
- while True:
- # Wait for the event to be set
- self._service_changed_request_event.wait(timeout = 5.0)
-
- # Stop if the application is shutting down
- if CuraApplication.getInstance().isShuttingDown():
- return
-
- self._service_changed_request_event.clear()
-
- # Handle all pending requests
- reschedule_requests = [] # A list of requests that have failed so later they will get re-scheduled
- while not self._service_changed_request_queue.empty():
- request = self._service_changed_request_queue.get()
- zeroconf, service_type, name, state_change = request
- try:
- result = self._onServiceChanged(zeroconf, service_type, name, state_change)
- if not result:
- reschedule_requests.append(request)
- except Exception:
- Logger.logException("e", "Failed to get service info for [%s] [%s], the request will be rescheduled",
- service_type, name)
- reschedule_requests.append(request)
-
- # Re-schedule the failed requests if any
- if reschedule_requests:
- for request in reschedule_requests:
- self._service_changed_request_queue.put(request)
-
- ## Handler for zeroConf detection.
- # Return True or False indicating if the process succeeded.
- # Note that this function can take over 3 seconds to complete. Be careful
- # calling it from the main thread.
- def _onServiceChanged(self, zero_conf, service_type, name, state_change):
- if state_change == ServiceStateChange.Added:
- # First try getting info from zero-conf cache
- info = ServiceInfo(service_type, name, properties = {})
- for record in zero_conf.cache.entries_with_name(name.lower()):
- info.update_record(zero_conf, time(), record)
-
- for record in zero_conf.cache.entries_with_name(info.server):
- info.update_record(zero_conf, time(), record)
- if info.address:
- break
-
- # Request more data if info is not complete
- if not info.address:
- info = zero_conf.get_service_info(service_type, name)
-
- if info:
- type_of_device = info.properties.get(b"type", None)
- if type_of_device:
- if type_of_device == b"printer":
- address = '.'.join(map(lambda n: str(n), info.address))
- self.addDeviceSignal.emit(str(name), address, info.properties)
- else:
- Logger.log("w",
- "The type of the found device is '%s', not 'printer'! Ignoring.." % type_of_device)
- else:
- Logger.log("w", "Could not get information about %s" % name)
- return False
-
- elif state_change == ServiceStateChange.Removed:
- Logger.log("d", "Bonjour service removed: %s" % name)
- self.removeDeviceSignal.emit(str(name))
-
- return True
-
- ## Check if the prerequsites are in place to start the cloud flow
- def checkCloudFlowIsPossible(self) -> None:
- Logger.log("d", "Checking if cloud connection is possible...")
-
- # Pre-Check: Skip if active machine already has been cloud connected or you said don't ask again
- active_machine = self._application.getMachineManager().activeMachine # type: Optional["GlobalStack"]
- if active_machine:
-
- # Check 1A: Printer isn't already configured for cloud
- if ConnectionType.CloudConnection.value in active_machine.configuredConnectionTypes:
- Logger.log("d", "Active machine was already configured for cloud.")
- return
-
- # Check 1B: Printer isn't already configured for cloud
- if active_machine.getMetaDataEntry("cloud_flow_complete", False):
- Logger.log("d", "Active machine was already configured for cloud.")
- return
-
- # Check 2: User did not already say "Don't ask me again"
- if active_machine.getMetaDataEntry("do_not_show_cloud_message", False):
- Logger.log("d", "Active machine shouldn't ask about cloud anymore.")
- return
+ ## Remove a manually connected networked printer.
+ def removeManualDevice(self, key: str, address: Optional[str] = None) -> None:
+ self._network_output_device_manager.removeManualDevice(key, address)
- # Check 3: User is logged in with an Ultimaker account
- if not self._account.isLoggedIn:
- Logger.log("d", "Cloud Flow not possible: User not logged in!")
- return
+ ## Get the discovered devices from the local network.
+ def getDiscoveredDevices(self) -> Dict[str, LocalClusterOutputDevice]:
+ return self._network_output_device_manager.getDiscoveredDevices()
- # Check 4: Machine is configured for network connectivity
- if not self._application.getMachineManager().activeMachineHasNetworkConnection:
- Logger.log("d", "Cloud Flow not possible: Machine is not connected!")
- return
-
- # Check 5: Machine has correct firmware version
- firmware_version = self._application.getMachineManager().activeMachineFirmwareVersion # type: str
- if not Version(firmware_version) > self._min_cloud_version:
- Logger.log("d", "Cloud Flow not possible: Machine firmware (%s) is too low! (Requires version %s)",
- firmware_version,
- self._min_cloud_version)
- return
-
- Logger.log("d", "Cloud flow is possible!")
- self.cloudFlowIsPossible.emit()
-
- def _onCloudFlowPossible(self) -> None:
- # Cloud flow is possible, so show the message
- if not self._start_cloud_flow_message:
- self._start_cloud_flow_message = Message(
- text = i18n_catalog.i18nc("@info:status", "Send and monitor print jobs from anywhere using your Ultimaker account."),
- lifetime = 0,
- image_source = QUrl.fromLocalFile(os.path.join(
- PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
- "resources", "svg", "cloud-flow-start.svg"
- )),
- image_caption = i18n_catalog.i18nc("@info:status", "Connect to Ultimaker Cloud"),
- option_text = i18n_catalog.i18nc("@action", "Don't ask me again for this printer."),
- option_state = False
- )
- self._start_cloud_flow_message.addAction("", i18n_catalog.i18nc("@action", "Get started"), "", "")
- self._start_cloud_flow_message.optionToggled.connect(self._onDontAskMeAgain)
- self._start_cloud_flow_message.actionTriggered.connect(self._onCloudFlowStarted)
- self._start_cloud_flow_message.show()
- return
-
- def _onCloudPrintingConfigured(self) -> None:
- if self._start_cloud_flow_message:
- self._start_cloud_flow_message.hide()
- self._start_cloud_flow_message = None
-
- # Show the successful pop-up
- if not self._start_cloud_flow_message:
- self._cloud_flow_complete_message = Message(
- text = i18n_catalog.i18nc("@info:status", "You can now send and monitor print jobs from anywhere using your Ultimaker account."),
- lifetime = 30,
- image_source = QUrl.fromLocalFile(os.path.join(
- PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
- "resources", "svg", "cloud-flow-completed.svg"
- )),
- image_caption = i18n_catalog.i18nc("@info:status", "Connected!")
- )
- # Don't show the review connection link if we're not on the local network
- if self._application.getMachineManager().activeMachineHasNetworkConnection:
- self._cloud_flow_complete_message.addAction("", i18n_catalog.i18nc("@action", "Review your connection"), "", "", 1) # TODO: Icon
- self._cloud_flow_complete_message.actionTriggered.connect(self._onReviewCloudConnection)
- self._cloud_flow_complete_message.show()
-
- # Set the machine's cloud flow as complete so we don't ask the user again and again for cloud connected printers
- active_machine = self._application.getMachineManager().activeMachine
- if active_machine:
- active_machine.setMetaDataEntry("do_not_show_cloud_message", True)
- return
-
- def _onDontAskMeAgain(self, checked: bool) -> None:
- active_machine = self._application.getMachineManager().activeMachine # type: Optional["GlobalStack"]
- if active_machine:
- active_machine.setMetaDataEntry("do_not_show_cloud_message", checked)
- if checked:
- Logger.log("d", "Will not ask the user again to cloud connect for current printer.")
- return
-
- def _onCloudFlowStarted(self, messageId: str, actionId: str) -> None:
- address = self._application.getMachineManager().activeMachineAddress # type: str
- if address:
- QDesktopServices.openUrl(QUrl("http://" + address + "/cloud_connect"))
- if self._start_cloud_flow_message:
- self._start_cloud_flow_message.hide()
- self._start_cloud_flow_message = None
- return
-
- def _onReviewCloudConnection(self, messageId: str, actionId: str) -> None:
- address = self._application.getMachineManager().activeMachineAddress # type: str
- if address:
- QDesktopServices.openUrl(QUrl("http://" + address + "/settings"))
- return
-
- def _onMachineSwitched(self) -> None:
- if self._start_cloud_flow_message is not None:
- self._start_cloud_flow_message.hide()
- self._start_cloud_flow_message = None
- if self._cloud_flow_complete_message is not None:
- self._cloud_flow_complete_message.hide()
- self._cloud_flow_complete_message = None
-
- self.checkCloudFlowIsPossible()
+ ## Connect the active machine to a device.
+ def associateActiveMachineWithPrinterDevice(self, device: LocalClusterOutputDevice) -> None:
+ self._network_output_device_manager.associateActiveMachineWithPrinterDevice(device)
diff --git a/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py
new file mode 100644
index 0000000000..8c5f5c12ea
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional, cast
+
+from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty, QObject
+
+from UM import i18nCatalog
+from cura.CuraApplication import CuraApplication
+from cura.MachineAction import MachineAction
+
+from .UM3OutputDevicePlugin import UM3OutputDevicePlugin
+from .Network.LocalClusterOutputDevice import LocalClusterOutputDevice
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## Machine action that allows to connect the active machine to a networked devices.
+# TODO: in the future this should be part of the new discovery workflow baked into Cura.
+class UltimakerNetworkedPrinterAction(MachineAction):
+
+ # Signal emitted when discovered devices have changed.
+ discoveredDevicesChanged = pyqtSignal()
+
+ def __init__(self) -> None:
+ super().__init__("DiscoverUM3Action", I18N_CATALOG.i18nc("@action", "Connect via Network"))
+ self._qml_url = "resources/qml/DiscoverUM3Action.qml"
+ self._network_plugin = None # type: Optional[UM3OutputDevicePlugin]
+
+ ## Override the default value.
+ def needsUserInteraction(self) -> bool:
+ return False
+
+ ## Start listening to network discovery events via the plugin.
+ @pyqtSlot(name = "startDiscovery")
+ def startDiscovery(self) -> None:
+ self._networkPlugin.discoveredDevicesChanged.connect(self._onDeviceDiscoveryChanged)
+ self.discoveredDevicesChanged.emit() # trigger at least once to populate the list
+
+ ## Reset the discovered devices.
+ @pyqtSlot(name = "reset")
+ def reset(self) -> None:
+ self.discoveredDevicesChanged.emit() # trigger to reset the list
+
+ ## Reset the discovered devices.
+ @pyqtSlot(name = "restartDiscovery")
+ def restartDiscovery(self) -> None:
+ self._networkPlugin.startDiscovery()
+ self.discoveredDevicesChanged.emit() # trigger to reset the list
+
+ ## Remove a manually added device.
+ @pyqtSlot(str, str, name = "removeManualDevice")
+ def removeManualDevice(self, key: str, address: str) -> None:
+ self._networkPlugin.removeManualDevice(key, address)
+
+ ## Add a new manual device. Can replace an existing one by key.
+ @pyqtSlot(str, str, name = "setManualDevice")
+ def setManualDevice(self, key: str, address: str) -> None:
+ if key != "":
+ self._networkPlugin.removeManualDevice(key)
+ if address != "":
+ self._networkPlugin.addManualDevice(address)
+
+ ## Get the devices discovered in the local network sorted by name.
+ @pyqtProperty("QVariantList", notify = discoveredDevicesChanged)
+ def foundDevices(self):
+ discovered_devices = list(self._networkPlugin.getDiscoveredDevices().values())
+ discovered_devices.sort(key = lambda d: d.name)
+ return discovered_devices
+
+ ## Connect a device selected in the list with the active machine.
+ @pyqtSlot(QObject, name = "associateActiveMachineWithPrinterDevice")
+ def associateActiveMachineWithPrinterDevice(self, device: LocalClusterOutputDevice) -> None:
+ self._networkPlugin.associateActiveMachineWithPrinterDevice(device)
+
+ ## Callback for when the list of discovered devices in the plugin was changed.
+ def _onDeviceDiscoveryChanged(self) -> None:
+ self.discoveredDevicesChanged.emit()
+
+ ## Get the network manager from the plugin.
+ @property
+ def _networkPlugin(self) -> UM3OutputDevicePlugin:
+ if not self._network_plugin:
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+ network_plugin = output_device_manager.getOutputDevicePlugin("UM3NetworkPrinting")
+ self._network_plugin = cast(UM3OutputDevicePlugin, network_plugin)
+ return self._network_plugin
diff --git a/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py
new file mode 100644
index 0000000000..73b5b456f9
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py
@@ -0,0 +1,353 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import os
+from time import time
+from typing import List, Optional, Dict
+
+from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, pyqtSlot, QUrl
+
+from UM.Logger import Logger
+from UM.Qt.Duration import Duration, DurationFormat
+from cura.CuraApplication import CuraApplication
+from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
+from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice, AuthState
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType, ConnectionState
+
+from .Utils import formatTimeCompleted, formatDateCompleted
+from .ClusterOutputController import ClusterOutputController
+from .Messages.PrintJobUploadProgressMessage import PrintJobUploadProgressMessage
+from .Messages.NotClusterHostMessage import NotClusterHostMessage
+from .Models.UM3PrintJobOutputModel import UM3PrintJobOutputModel
+from .Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
+from .Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
+
+
+## Output device class that forms the basis of Ultimaker networked printer output devices.
+# Currently used for local networking and cloud printing using Ultimaker Connect.
+# This base class primarily contains all the Qt properties and slots needed for the monitor page to work.
+class UltimakerNetworkedPrinterOutputDevice(NetworkedPrinterOutputDevice):
+
+ META_NETWORK_KEY = "um_network_key"
+ META_CLUSTER_ID = "um_cloud_cluster_id"
+
+ # Signal emitted when the status of the print jobs for this cluster were changed over the network.
+ printJobsChanged = pyqtSignal()
+
+ # Signal emitted when the currently visible printer card in the UI was changed by the user.
+ activePrinterChanged = pyqtSignal()
+
+ # Notify can only use signals that are defined by the class that they are in, not inherited ones.
+ # Therefore we create a private signal used to trigger the printersChanged signal.
+ _clusterPrintersChanged = pyqtSignal()
+
+ # States indicating if a print job is queued.
+ QUEUED_PRINT_JOBS_STATES = {"queued", "error"}
+
+ # Time in seconds since last network response after which we consider this device offline.
+ # We set this a bit higher than some of the other intervals to make sure they don't overlap.
+ NETWORK_RESPONSE_CONSIDER_OFFLINE = 10.0 # seconds
+
+ def __init__(self, device_id: str, address: str, properties: Dict[bytes, bytes], connection_type: ConnectionType,
+ parent=None) -> None:
+
+ super().__init__(device_id=device_id, address=address, properties=properties, connection_type=connection_type,
+ parent=parent)
+
+ # Trigger the printersChanged signal when the private signal is triggered.
+ self.printersChanged.connect(self._clusterPrintersChanged)
+
+ # Keeps track the last network response to determine if we are still connected.
+ self._time_of_last_response = time()
+ self._time_of_last_request = time()
+
+ # Set the display name from the properties.
+ self.setName(self.getProperty("name"))
+
+ # Set the display name of the printer type.
+ definitions = CuraApplication.getInstance().getContainerRegistry().findContainers(id = self.printerType)
+ self._printer_type_name = definitions[0].getName() if definitions else ""
+
+ # Keeps track of all printers in the cluster.
+ self._printers = [] # type: List[PrinterOutputModel]
+ self._has_received_printers = False
+
+ # Keeps track of all print jobs in the cluster.
+ self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
+
+ # Keep track of the printer currently selected in the UI.
+ self._active_printer = None # type: Optional[PrinterOutputModel]
+
+ # By default we are not authenticated. This state will be changed later.
+ self._authentication_state = AuthState.NotAuthenticated
+
+ # Load the Monitor UI elements.
+ self._loadMonitorTab()
+
+ # The job upload progress message modal.
+ self._progress = PrintJobUploadProgressMessage()
+
+ ## The IP address of the printer.
+ @pyqtProperty(str, constant=True)
+ def address(self) -> str:
+ return self._address
+
+ ## The display name of the printer.
+ @pyqtProperty(str, constant=True)
+ def printerTypeName(self) -> str:
+ return self._printer_type_name
+
+ # Get all print jobs for this cluster.
+ @pyqtProperty("QVariantList", notify=printJobsChanged)
+ def printJobs(self) -> List[UM3PrintJobOutputModel]:
+ return self._print_jobs
+
+ # Get all print jobs for this cluster that are queued.
+ @pyqtProperty("QVariantList", notify=printJobsChanged)
+ def queuedPrintJobs(self) -> List[UM3PrintJobOutputModel]:
+ return [print_job for print_job in self._print_jobs if print_job.state in self.QUEUED_PRINT_JOBS_STATES]
+
+ # Get all print jobs for this cluster that are currently printing.
+ @pyqtProperty("QVariantList", notify=printJobsChanged)
+ def activePrintJobs(self) -> List[UM3PrintJobOutputModel]:
+ return [print_job for print_job in self._print_jobs if
+ print_job.assignedPrinter is not None and print_job.state not in self.QUEUED_PRINT_JOBS_STATES]
+
+ @pyqtProperty(bool, notify=_clusterPrintersChanged)
+ def receivedData(self) -> bool:
+ return self._has_received_printers
+
+ # Get the amount of printers in the cluster.
+ @pyqtProperty(int, notify=_clusterPrintersChanged)
+ def clusterSize(self) -> int:
+ if not self._has_received_printers:
+ discovered_size = self.getProperty("cluster_size")
+ if discovered_size == "":
+ return 1 # prevent false positives for new devices
+ return int(discovered_size)
+ return len(self._printers)
+
+ # Get the amount of printer in the cluster per type.
+ @pyqtProperty("QVariantList", notify=_clusterPrintersChanged)
+ def connectedPrintersTypeCount(self) -> List[Dict[str, str]]:
+ printer_count = {} # type: Dict[str, int]
+ for printer in self._printers:
+ if printer.type in printer_count:
+ printer_count[printer.type] += 1
+ else:
+ printer_count[printer.type] = 1
+ result = []
+ for machine_type in printer_count:
+ result.append({"machine_type": machine_type, "count": str(printer_count[machine_type])})
+ return result
+
+ # Get a list of all printers.
+ @pyqtProperty("QVariantList", notify=_clusterPrintersChanged)
+ def printers(self) -> List[PrinterOutputModel]:
+ return self._printers
+
+ # Get the currently active printer in the UI.
+ @pyqtProperty(QObject, notify=activePrinterChanged)
+ def activePrinter(self) -> Optional[PrinterOutputModel]:
+ return self._active_printer
+
+ # Set the currently active printer from the UI.
+ @pyqtSlot(QObject, name="setActivePrinter")
+ def setActivePrinter(self, printer: Optional[PrinterOutputModel]) -> None:
+ if self.activePrinter == printer:
+ return
+ self._active_printer = printer
+ self.activePrinterChanged.emit()
+
+ ## Whether the printer that this output device represents supports print job actions via the local network.
+ @pyqtProperty(bool, constant=True)
+ def supportsPrintJobActions(self) -> bool:
+ return True
+
+ ## Set the remote print job state.
+ def setJobState(self, print_job_uuid: str, state: str) -> None:
+ raise NotImplementedError("setJobState must be implemented")
+
+ @pyqtSlot(str, name="sendJobToTop")
+ def sendJobToTop(self, print_job_uuid: str) -> None:
+ raise NotImplementedError("sendJobToTop must be implemented")
+
+ @pyqtSlot(str, name="deleteJobFromQueue")
+ def deleteJobFromQueue(self, print_job_uuid: str) -> None:
+ raise NotImplementedError("deleteJobFromQueue must be implemented")
+
+ @pyqtSlot(str, name="forceSendJob")
+ def forceSendJob(self, print_job_uuid: str) -> None:
+ raise NotImplementedError("forceSendJob must be implemented")
+
+ @pyqtSlot(name="openPrintJobControlPanel")
+ def openPrintJobControlPanel(self) -> None:
+ raise NotImplementedError("openPrintJobControlPanel must be implemented")
+
+ @pyqtSlot(name="openPrinterControlPanel")
+ def openPrinterControlPanel(self) -> None:
+ raise NotImplementedError("openPrinterControlPanel must be implemented")
+
+ @pyqtProperty(QUrl, notify=_clusterPrintersChanged)
+ def activeCameraUrl(self) -> QUrl:
+ return QUrl()
+
+ @pyqtSlot(QUrl, name="setActiveCameraUrl")
+ def setActiveCameraUrl(self, camera_url: QUrl) -> None:
+ pass
+
+ @pyqtSlot(int, result=str, name="getTimeCompleted")
+ def getTimeCompleted(self, time_remaining: int) -> str:
+ return formatTimeCompleted(time_remaining)
+
+ @pyqtSlot(int, result=str, name="getDateCompleted")
+ def getDateCompleted(self, time_remaining: int) -> str:
+ return formatDateCompleted(time_remaining)
+
+ @pyqtSlot(int, result=str, name="formatDuration")
+ def formatDuration(self, seconds: int) -> str:
+ return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
+
+ def _update(self) -> None:
+ self._checkStillConnected()
+ super()._update()
+
+ ## Check if we're still connected by comparing the last timestamps for network response and the current time.
+ # This implementation is similar to the base NetworkedPrinterOutputDevice, but is tweaked slightly.
+ # Re-connecting is handled automatically by the output device managers in this plugin.
+ # TODO: it would be nice to have this logic in the managers, but connecting those with signals causes crashes.
+ def _checkStillConnected(self) -> None:
+ time_since_last_response = time() - self._time_of_last_response
+ if time_since_last_response > self.NETWORK_RESPONSE_CONSIDER_OFFLINE:
+ self.setConnectionState(ConnectionState.Closed)
+ if self.key in CuraApplication.getInstance().getOutputDeviceManager().getOutputDeviceIds():
+ CuraApplication.getInstance().getOutputDeviceManager().removeOutputDevice(self.key)
+ elif self.connectionState == ConnectionState.Closed:
+ self._reconnectForActiveMachine()
+
+ ## Reconnect for the active output device.
+ # Does nothing if the device is not meant for the active machine.
+ def _reconnectForActiveMachine(self) -> None:
+ active_machine = CuraApplication.getInstance().getGlobalContainerStack()
+ if not active_machine:
+ return
+
+ # Indicate this device is now connected again.
+ self.setConnectionState(ConnectionState.Connected)
+
+ # If the device was already registered we don't need to register it again.
+ if self.key in CuraApplication.getInstance().getOutputDeviceManager().getOutputDeviceIds():
+ return
+
+ # Try for local network device.
+ stored_device_id = active_machine.getMetaDataEntry(self.META_NETWORK_KEY)
+ if self.key == stored_device_id:
+ CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(self)
+
+ # Try for cloud device.
+ stored_cluster_id = active_machine.getMetaDataEntry(self.META_CLUSTER_ID)
+ if self.key == stored_cluster_id:
+ CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(self)
+
+ def _responseReceived(self) -> None:
+ self._time_of_last_response = time()
+
+ def _updatePrinters(self, remote_printers: List[ClusterPrinterStatus]) -> None:
+ self._responseReceived()
+
+ # Keep track of the new printers to show.
+ # We create a new list instead of changing the existing one to get the correct order.
+ new_printers = [] # type: List[PrinterOutputModel]
+
+ # Check which printers need to be created or updated.
+ for index, printer_data in enumerate(remote_printers):
+ printer = next(iter(printer for printer in self._printers if printer.key == printer_data.uuid), None)
+ if printer is None:
+ printer = printer_data.createOutputModel(ClusterOutputController(self))
+ else:
+ printer_data.updateOutputModel(printer)
+ new_printers.append(printer)
+
+ # Check which printers need to be removed (de-referenced).
+ remote_printers_keys = [printer_data.uuid for printer_data in remote_printers]
+ removed_printers = [printer for printer in self._printers if printer.key not in remote_printers_keys]
+ for removed_printer in removed_printers:
+ if self._active_printer and self._active_printer.key == removed_printer.key:
+ self.setActivePrinter(None)
+
+ self._printers = new_printers
+ self._has_received_printers = True
+ if self._printers and not self.activePrinter:
+ self.setActivePrinter(self._printers[0])
+
+ self.printersChanged.emit()
+ self._checkIfClusterHost()
+
+ ## Check is this device is a cluster host and takes the needed actions when it is not.
+ def _checkIfClusterHost(self):
+ if len(self._printers) < 1 and self.isConnected():
+ NotClusterHostMessage(self).show()
+ self.close()
+ CuraApplication.getInstance().getOutputDeviceManager().removeOutputDevice(self.key)
+
+ ## Updates the local list of print jobs with the list received from the cluster.
+ # \param remote_jobs: The print jobs received from the cluster.
+ def _updatePrintJobs(self, remote_jobs: List[ClusterPrintJobStatus]) -> None:
+ self._responseReceived()
+
+ # Keep track of the new print jobs to show.
+ # We create a new list instead of changing the existing one to get the correct order.
+ new_print_jobs = []
+
+ # Check which print jobs need to be created or updated.
+ for index, print_job_data in enumerate(remote_jobs):
+ print_job = next(
+ iter(print_job for print_job in self._print_jobs if print_job.key == print_job_data.uuid), None)
+ if not print_job:
+ new_print_jobs.append(self._createPrintJobModel(print_job_data))
+ else:
+ print_job_data.updateOutputModel(print_job)
+ if print_job_data.printer_uuid:
+ self._updateAssignedPrinter(print_job, print_job_data.printer_uuid)
+ if print_job_data.assigned_to:
+ self._updateAssignedPrinter(print_job, print_job_data.assigned_to)
+ new_print_jobs.append(print_job)
+
+ # Check which print job need to be removed (de-referenced).
+ remote_job_keys = [print_job_data.uuid for print_job_data in remote_jobs]
+ removed_jobs = [print_job for print_job in self._print_jobs if print_job.key not in remote_job_keys]
+ for removed_job in removed_jobs:
+ if removed_job.assignedPrinter:
+ removed_job.assignedPrinter.updateActivePrintJob(None)
+
+ self._print_jobs = new_print_jobs
+ self.printJobsChanged.emit()
+
+ ## Create a new print job model based on the remote status of the job.
+ # \param remote_job: The remote print job data.
+ def _createPrintJobModel(self, remote_job: ClusterPrintJobStatus) -> UM3PrintJobOutputModel:
+ model = remote_job.createOutputModel(ClusterOutputController(self))
+ if remote_job.printer_uuid:
+ self._updateAssignedPrinter(model, remote_job.printer_uuid)
+ if remote_job.assigned_to:
+ self._updateAssignedPrinter(model, remote_job.assigned_to)
+ return model
+
+ ## Updates the printer assignment for the given print job model.
+ def _updateAssignedPrinter(self, model: UM3PrintJobOutputModel, printer_uuid: str) -> None:
+ printer = next((p for p in self._printers if printer_uuid == p.key), None)
+ if not printer:
+ return
+ printer.updateActivePrintJob(model)
+ model.updateAssignedPrinter(printer)
+
+ ## Load Monitor tab QML.
+ def _loadMonitorTab(self) -> None:
+ plugin_registry = CuraApplication.getInstance().getPluginRegistry()
+ if not plugin_registry:
+ Logger.log("e", "Could not get plugin registry")
+ return
+ plugin_path = plugin_registry.getPluginPath("UM3NetworkPrinting")
+ if not plugin_path:
+ Logger.log("e", "Could not get plugin path")
+ return
+ self._monitor_view_qml_path = os.path.join(plugin_path, "resources", "qml", "MonitorStage.qml")
diff --git a/plugins/UM3NetworkPrinting/src/Utils.py b/plugins/UM3NetworkPrinting/src/Utils.py
new file mode 100644
index 0000000000..a628130416
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Utils.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from datetime import datetime, timedelta
+
+from UM import i18nCatalog
+
+
+def formatTimeCompleted(seconds_remaining: int) -> str:
+ completed = datetime.now() + timedelta(seconds=seconds_remaining)
+ return "{hour:02d}:{minute:02d}".format(hour = completed.hour, minute = completed.minute)
+
+
+def formatDateCompleted(seconds_remaining: int) -> str:
+ now = datetime.now()
+ completed = now + timedelta(seconds=seconds_remaining)
+ days = (completed.date() - now.date()).days
+ i18n = i18nCatalog("cura")
+
+ # If finishing date is more than 7 days out, using "Mon Dec 3 at HH:MM" format
+ if days >= 7:
+ return completed.strftime("%a %b ") + "{day}".format(day = completed.day)
+ # If finishing date is within the next week, use "Monday at HH:MM" format
+ elif days >= 2:
+ return completed.strftime("%a")
+ # If finishing tomorrow, use "tomorrow at HH:MM" format
+ elif days >= 1:
+ return i18n.i18nc("@info:status", "tomorrow")
+ # If finishing today, use "today at HH:MM" format
+ else:
+ return i18n.i18nc("@info:status", "today")
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/__init__.py b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/__init__.py
deleted file mode 100644
index 777afc92c2..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-import json
-import os
-
-
-def readFixture(fixture_name: str) -> bytes:
- with open("{}/{}.json".format(os.path.dirname(__file__), fixture_name), "rb") as f:
- return f.read()
-
-def parseFixture(fixture_name: str) -> dict:
- return json.loads(readFixture(fixture_name).decode())
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusterStatusResponse.json b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusterStatusResponse.json
deleted file mode 100644
index 4f9f47fc75..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusterStatusResponse.json
+++ /dev/null
@@ -1,95 +0,0 @@
-{
- "data": {
- "generated_time": "2018-12-10T08:23:55.110Z",
- "printers": [
- {
- "configuration": [
- {
- "extruder_index": 0,
- "material": {
- "material": "empty"
- },
- "print_core_id": "AA 0.4"
- },
- {
- "extruder_index": 1,
- "material": {
- "material": "empty"
- },
- "print_core_id": "AA 0.4"
- }
- ],
- "enabled": true,
- "firmware_version": "5.1.2.20180807",
- "friendly_name": "Master-Luke",
- "ip_address": "10.183.1.140",
- "machine_variant": "Ultimaker 3",
- "status": "maintenance",
- "unique_name": "ultimakersystem-ccbdd30044ec",
- "uuid": "b3a47ea3-1eeb-4323-9626-6f9c3c888f9e"
- },
- {
- "configuration": [
- {
- "extruder_index": 0,
- "material": {
- "brand": "Generic",
- "color": "Generic",
- "guid": "506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9",
- "material": "PLA"
- },
- "print_core_id": "AA 0.4"
- },
- {
- "extruder_index": 1,
- "material": {
- "brand": "Ultimaker",
- "color": "Red",
- "guid": "9cfe5bf1-bdc5-4beb-871a-52c70777842d",
- "material": "PLA"
- },
- "print_core_id": "AA 0.4"
- }
- ],
- "enabled": true,
- "firmware_version": "4.3.3.20180529",
- "friendly_name": "UM-Marijn",
- "ip_address": "10.183.1.166",
- "machine_variant": "Ultimaker 3",
- "status": "idle",
- "unique_name": "ultimakersystem-ccbdd30058ab",
- "uuid": "6e62c40a-4601-4b0e-9fec-c7c02c59c30a"
- }
- ],
- "print_jobs": [
- {
- "assigned_to": "6e62c40a-4601-4b0e-9fec-c7c02c59c30a",
- "configuration": [
- {
- "extruder_index": 0,
- "material": {
- "brand": "Ultimaker",
- "color": "Black",
- "guid": "3ee70a86-77d8-4b87-8005-e4a1bc57d2ce",
- "material": "PLA"
- },
- "print_core_id": "AA 0.4"
- }
- ],
- "constraints": {},
- "created_at": "2018-12-10T08:28:04.108Z",
- "force": false,
- "last_seen": 500165.109491861,
- "machine_variant": "Ultimaker 3",
- "name": "UM3_dragon",
- "network_error_count": 0,
- "owner": "Daniel Testing",
- "started": false,
- "status": "queued",
- "time_elapsed": 0,
- "time_total": 14145,
- "uuid": "d1c8bd52-5e9f-486a-8c25-a123cc8c7702"
- }
- ]
- }
-}
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusters.json b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusters.json
deleted file mode 100644
index 5200e3b971..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusters.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "data": [{
- "cluster_id": "RIZ6cZbWA_Ua7RZVJhrdVfVpf0z-MqaSHQE4v8aRTtYq",
- "host_guid": "e90ae0ac-1257-4403-91ee-a44c9b7e8050",
- "host_name": "ultimakersystem-ccbdd30044ec",
- "host_version": "5.0.0.20170101",
- "is_online": true,
- "status": "active"
- }, {
- "cluster_id": "NWKV6vJP_LdYsXgXqAcaNCR0YcLJwar1ugh0ikEZsZs8",
- "host_guid": "e0ace90a-91ee-1257-4403-e8050a44c9b7",
- "host_name": "ultimakersystem-30044ecccbdd",
- "host_version": "5.1.2.20180807",
- "is_online": true,
- "status": "active"
- }]
-}
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/postJobPrintResponse.json b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/postJobPrintResponse.json
deleted file mode 100644
index caedcd8732..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/postJobPrintResponse.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "data": {
- "cluster_job_id": "9a59d8e9-91d3-4ff6-b4cb-9db91c4094dd",
- "job_id": "ABCDefGHIjKlMNOpQrSTUvYxWZ0-1234567890abcDE=",
- "status": "queued",
- "generated_time": "2018-12-10T08:23:55.110Z"
- }
-}
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/putJobUploadResponse.json b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/putJobUploadResponse.json
deleted file mode 100644
index 1304f3a9f6..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/putJobUploadResponse.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "data": {
- "content_type": "text/plain",
- "job_id": "ABCDefGHIjKlMNOpQrSTUvYxWZ0-1234567890abcDE=",
- "job_name": "Ultimaker Robot v3.0",
- "status": "uploading",
- "upload_url": "https://api.ultimaker.com/print-job-upload"
- }
-}
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Models/__init__.py b/plugins/UM3NetworkPrinting/tests/Cloud/Models/__init__.py
deleted file mode 100644
index f3f6970c54..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/Models/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/NetworkManagerMock.py b/plugins/UM3NetworkPrinting/tests/Cloud/NetworkManagerMock.py
deleted file mode 100644
index e504509d67..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/NetworkManagerMock.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-import json
-from typing import Dict, Tuple, Union, Optional, Any
-from unittest.mock import MagicMock
-
-from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
-
-from UM.Logger import Logger
-from UM.Signal import Signal
-
-
-class FakeSignal:
- def __init__(self):
- self._callbacks = []
-
- def connect(self, callback):
- self._callbacks.append(callback)
-
- def disconnect(self, callback):
- self._callbacks.remove(callback)
-
- def emit(self, *args, **kwargs):
- for callback in self._callbacks:
- callback(*args, **kwargs)
-
-
-## This class can be used to mock the QNetworkManager class and test the code using it.
-# After patching the QNetworkManager class, requests are prepared before they can be executed.
-# Any requests not prepared beforehand will cause KeyErrors.
-class NetworkManagerMock:
-
- # An enumeration of the supported operations and their code for the network access manager.
- _OPERATIONS = {
- "GET": QNetworkAccessManager.GetOperation,
- "POST": QNetworkAccessManager.PostOperation,
- "PUT": QNetworkAccessManager.PutOperation,
- "DELETE": QNetworkAccessManager.DeleteOperation,
- "HEAD": QNetworkAccessManager.HeadOperation,
- } # type: Dict[str, int]
-
- ## Initializes the network manager mock.
- def __init__(self) -> None:
- # A dict with the prepared replies, using the format {(http_method, url): reply}
- self.replies = {} # type: Dict[Tuple[str, str], MagicMock]
- self.request_bodies = {} # type: Dict[Tuple[str, str], bytes]
-
- # Signals used in the network manager.
- self.finished = Signal()
- self.authenticationRequired = Signal()
-
- ## Mock implementation of the get, post, put, delete and head methods from the network manager.
- # Since the methods are very simple and the same it didn't make sense to repeat the code.
- # \param method: The method being called.
- # \return The mocked function, if the method name is known. Defaults to the standard getattr function.
- def __getattr__(self, method: str) -> Any:
- ## This mock implementation will simply return the reply from the prepared ones.
- # it raises a KeyError if requests are done without being prepared.
- def doRequest(request: QNetworkRequest, body: Optional[bytes] = None, *_):
- key = method.upper(), request.url().toString()
- if body:
- self.request_bodies[key] = body
- return self.replies[key]
-
- operation = self._OPERATIONS.get(method.upper())
- if operation:
- return doRequest
-
- # the attribute is not one of the implemented methods, default to the standard implementation.
- return getattr(super(), method)
-
- ## Prepares a server reply for the given parameters.
- # \param method: The HTTP method.
- # \param url: The URL being requested.
- # \param status_code: The HTTP status code for the response.
- # \param response: The response body from the server (generally json-encoded).
- def prepareReply(self, method: str, url: str, status_code: int, response: Union[bytes, dict]) -> None:
- reply_mock = MagicMock()
- reply_mock.url().toString.return_value = url
- reply_mock.operation.return_value = self._OPERATIONS[method]
- reply_mock.attribute.return_value = status_code
- reply_mock.finished = FakeSignal()
- reply_mock.isFinished.return_value = False
- reply_mock.readAll.return_value = response if isinstance(response, bytes) else json.dumps(response).encode()
- self.replies[method, url] = reply_mock
- Logger.log("i", "Prepared mock {}-response to {} {}", status_code, method, url)
-
- ## Gets the request that was sent to the network manager for the given method and URL.
- # \param method: The HTTP method.
- # \param url: The URL.
- def getRequestBody(self, method: str, url: str) -> Optional[bytes]:
- return self.request_bodies.get((method.upper(), url))
-
- ## Emits the signal that the reply is ready to all prepared replies.
- def flushReplies(self) -> None:
- for key, reply in self.replies.items():
- Logger.log("i", "Flushing reply to {} {}", *key)
- reply.isFinished.return_value = True
- reply.finished.emit()
- self.finished.emit(reply)
- self.reset()
-
- ## Deletes all prepared replies
- def reset(self) -> None:
- self.replies.clear()
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudApiClient.py b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudApiClient.py
deleted file mode 100644
index b79d009c31..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudApiClient.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from typing import List
-from unittest import TestCase
-from unittest.mock import patch, MagicMock
-
-from cura.UltimakerCloudAuthentication import CuraCloudAPIRoot
-from ...src.Cloud import CloudApiClient
-from ...src.Cloud.Models.CloudClusterResponse import CloudClusterResponse
-from ...src.Cloud.Models.CloudClusterStatus import CloudClusterStatus
-from ...src.Cloud.Models.CloudPrintJobResponse import CloudPrintJobResponse
-from ...src.Cloud.Models.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest
-from ...src.Cloud.Models.CloudError import CloudError
-from .Fixtures import readFixture, parseFixture
-from .NetworkManagerMock import NetworkManagerMock
-
-
-class TestCloudApiClient(TestCase):
- maxDiff = None
-
- def _errorHandler(self, errors: List[CloudError]):
- raise Exception("Received unexpected error: {}".format(errors))
-
- def setUp(self):
- super().setUp()
- self.account = MagicMock()
- self.account.isLoggedIn.return_value = True
-
- self.network = NetworkManagerMock()
- with patch.object(CloudApiClient, 'QNetworkAccessManager', return_value = self.network):
- self.api = CloudApiClient.CloudApiClient(self.account, self._errorHandler)
-
- def test_getClusters(self):
- result = []
-
- response = readFixture("getClusters")
- data = parseFixture("getClusters")["data"]
-
- self.network.prepareReply("GET", CuraCloudAPIRoot + "/connect/v1/clusters", 200, response)
- # The callback is a function that adds the result of the call to getClusters to the result list
- self.api.getClusters(lambda clusters: result.extend(clusters))
-
- self.network.flushReplies()
-
- self.assertEqual([CloudClusterResponse(**data[0]), CloudClusterResponse(**data[1])], result)
-
- def test_getClusterStatus(self):
- result = []
-
- response = readFixture("getClusterStatusResponse")
- data = parseFixture("getClusterStatusResponse")["data"]
-
- url = CuraCloudAPIRoot + "/connect/v1/clusters/R0YcLJwar1ugh0ikEZsZs8NWKV6vJP_LdYsXgXqAcaNC/status"
- self.network.prepareReply("GET", url, 200, response)
- self.api.getClusterStatus("R0YcLJwar1ugh0ikEZsZs8NWKV6vJP_LdYsXgXqAcaNC", lambda s: result.append(s))
-
- self.network.flushReplies()
-
- self.assertEqual([CloudClusterStatus(**data)], result)
-
- def test_requestUpload(self):
-
- results = []
-
- response = readFixture("putJobUploadResponse")
-
- self.network.prepareReply("PUT", CuraCloudAPIRoot + "/cura/v1/jobs/upload", 200, response)
- request = CloudPrintJobUploadRequest(job_name = "job name", file_size = 143234, content_type = "text/plain")
- self.api.requestUpload(request, lambda r: results.append(r))
- self.network.flushReplies()
-
- self.assertEqual(["text/plain"], [r.content_type for r in results])
- self.assertEqual(["uploading"], [r.status for r in results])
-
- def test_uploadToolPath(self):
-
- results = []
- progress = MagicMock()
-
- data = parseFixture("putJobUploadResponse")["data"]
- upload_response = CloudPrintJobResponse(**data)
-
- # Network client doesn't look into the reply
- self.network.prepareReply("PUT", upload_response.upload_url, 200, b'{}')
-
- mesh = ("1234" * 100000).encode()
- self.api.uploadToolPath(upload_response, mesh, lambda: results.append("sent"), progress.advance, progress.error)
-
- for _ in range(10):
- self.network.flushReplies()
- self.network.prepareReply("PUT", upload_response.upload_url, 200, b'{}')
-
- self.assertEqual(["sent"], results)
-
- def test_requestPrint(self):
-
- results = []
-
- response = readFixture("postJobPrintResponse")
-
- cluster_id = "NWKV6vJP_LdYsXgXqAcaNCR0YcLJwar1ugh0ikEZsZs8"
- cluster_job_id = "9a59d8e9-91d3-4ff6-b4cb-9db91c4094dd"
- job_id = "ABCDefGHIjKlMNOpQrSTUvYxWZ0-1234567890abcDE="
-
- self.network.prepareReply("POST",
- CuraCloudAPIRoot + "/connect/v1/clusters/{}/print/{}"
- .format(cluster_id, job_id),
- 200, response)
-
- self.api.requestPrint(cluster_id, job_id, lambda r: results.append(r))
-
- self.network.flushReplies()
-
- self.assertEqual([job_id], [r.job_id for r in results])
- self.assertEqual([cluster_job_id], [r.cluster_job_id for r in results])
- self.assertEqual(["queued"], [r.status for r in results])
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDevice.py b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDevice.py
deleted file mode 100644
index c4d891302e..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDevice.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-import json
-from unittest import TestCase
-from unittest.mock import patch, MagicMock
-
-from UM.Scene.SceneNode import SceneNode
-from cura.UltimakerCloudAuthentication import CuraCloudAPIRoot
-from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-from ...src.Cloud import CloudApiClient
-from ...src.Cloud.CloudOutputDevice import CloudOutputDevice
-from ...src.Cloud.Models.CloudClusterResponse import CloudClusterResponse
-from .Fixtures import readFixture, parseFixture
-from .NetworkManagerMock import NetworkManagerMock
-
-
-class TestCloudOutputDevice(TestCase):
- maxDiff = None
-
- CLUSTER_ID = "RIZ6cZbWA_Ua7RZVJhrdVfVpf0z-MqaSHQE4v8aRTtYq"
- JOB_ID = "ABCDefGHIjKlMNOpQrSTUvYxWZ0-1234567890abcDE="
- HOST_NAME = "ultimakersystem-ccbdd30044ec"
- HOST_GUID = "e90ae0ac-1257-4403-91ee-a44c9b7e8050"
- HOST_VERSION = "5.2.0"
-
- STATUS_URL = "{}/connect/v1/clusters/{}/status".format(CuraCloudAPIRoot, CLUSTER_ID)
- PRINT_URL = "{}/connect/v1/clusters/{}/print/{}".format(CuraCloudAPIRoot, CLUSTER_ID, JOB_ID)
- REQUEST_UPLOAD_URL = "{}/cura/v1/jobs/upload".format(CuraCloudAPIRoot)
-
- def setUp(self):
- super().setUp()
- self.app = MagicMock()
-
- self.patches = [patch("UM.Qt.QtApplication.QtApplication.getInstance", return_value=self.app),
- patch("UM.Application.Application.getInstance", return_value=self.app)]
- for patched_method in self.patches:
- patched_method.start()
-
- self.cluster = CloudClusterResponse(self.CLUSTER_ID, self.HOST_GUID, self.HOST_NAME, is_online=True,
- status="active", host_version=self.HOST_VERSION)
-
- self.network = NetworkManagerMock()
- self.account = MagicMock(isLoggedIn=True, accessToken="TestAccessToken")
- self.onError = MagicMock()
- with patch.object(CloudApiClient, "QNetworkAccessManager", return_value = self.network):
- self._api = CloudApiClient.CloudApiClient(self.account, self.onError)
-
- self.device = CloudOutputDevice(self._api, self.cluster)
- self.cluster_status = parseFixture("getClusterStatusResponse")
- self.network.prepareReply("GET", self.STATUS_URL, 200, readFixture("getClusterStatusResponse"))
-
- def tearDown(self):
- try:
- super().tearDown()
- self.network.flushReplies()
- finally:
- for patched_method in self.patches:
- patched_method.stop()
-
- # We test for these in order to make sure the correct file type is selected depending on the firmware version.
- def test_properties(self):
- self.assertEqual(self.device.firmwareVersion, self.HOST_VERSION)
- self.assertEqual(self.device.name, self.HOST_NAME)
-
- def test_status(self):
- self.device._update()
- self.network.flushReplies()
-
- self.assertEqual([PrinterOutputModel, PrinterOutputModel], [type(printer) for printer in self.device.printers])
-
- controller_fields = {
- "_output_device": self.device,
- "can_abort": False,
- "can_control_manually": False,
- "can_pause": False,
- "can_pre_heat_bed": False,
- "can_pre_heat_hotends": False,
- "can_send_raw_gcode": False,
- "can_update_firmware": False,
- }
-
- self.assertEqual({printer["uuid"] for printer in self.cluster_status["data"]["printers"]},
- {printer.key for printer in self.device.printers})
- self.assertEqual([controller_fields, controller_fields],
- [printer.getController().__dict__ for printer in self.device.printers])
-
- self.assertEqual(["UM3PrintJobOutputModel"], [type(printer).__name__ for printer in self.device.printJobs])
- self.assertEqual({job["uuid"] for job in self.cluster_status["data"]["print_jobs"]},
- {job.key for job in self.device.printJobs})
- self.assertEqual({job["owner"] for job in self.cluster_status["data"]["print_jobs"]},
- {job.owner for job in self.device.printJobs})
- self.assertEqual({job["name"] for job in self.cluster_status["data"]["print_jobs"]},
- {job.name for job in self.device.printJobs})
-
- def test_remove_print_job(self):
- self.device._update()
- self.network.flushReplies()
- self.assertEqual(1, len(self.device.printJobs))
-
- self.cluster_status["data"]["print_jobs"].clear()
- self.network.prepareReply("GET", self.STATUS_URL, 200, self.cluster_status)
-
- self.device._last_request_time = None
- self.device._update()
- self.network.flushReplies()
- self.assertEqual([], self.device.printJobs)
-
- def test_remove_printers(self):
- self.device._update()
- self.network.flushReplies()
- self.assertEqual(2, len(self.device.printers))
-
- self.cluster_status["data"]["printers"].clear()
- self.network.prepareReply("GET", self.STATUS_URL, 200, self.cluster_status)
-
- self.device._last_request_time = None
- self.device._update()
- self.network.flushReplies()
- self.assertEqual([], self.device.printers)
-
- def test_print_to_cloud(self):
- active_machine_mock = self.app.getGlobalContainerStack.return_value
- active_machine_mock.getMetaDataEntry.side_effect = {"file_formats": "application/x-ufp"}.get
-
- request_upload_response = parseFixture("putJobUploadResponse")
- request_print_response = parseFixture("postJobPrintResponse")
- self.network.prepareReply("PUT", self.REQUEST_UPLOAD_URL, 201, request_upload_response)
- self.network.prepareReply("PUT", request_upload_response["data"]["upload_url"], 201, b"{}")
- self.network.prepareReply("POST", self.PRINT_URL, 200, request_print_response)
-
- file_handler = MagicMock()
- file_handler.getSupportedFileTypesWrite.return_value = [{
- "extension": "ufp",
- "mime_type": "application/x-ufp",
- "mode": 2
- }, {
- "extension": "gcode.gz",
- "mime_type": "application/gzip",
- "mode": 2,
- }]
- file_handler.getWriterByMimeType.return_value.write.side_effect = \
- lambda stream, nodes: stream.write(str(nodes).encode())
-
- scene_nodes = [SceneNode()]
- expected_mesh = str(scene_nodes).encode()
- self.device.requestWrite(scene_nodes, file_handler=file_handler, file_name="FileName")
-
- self.network.flushReplies()
- self.assertEqual(
- {"data": {"content_type": "application/x-ufp", "file_size": len(expected_mesh), "job_name": "FileName"}},
- json.loads(self.network.getRequestBody("PUT", self.REQUEST_UPLOAD_URL).decode())
- )
- self.assertEqual(expected_mesh,
- self.network.getRequestBody("PUT", request_upload_response["data"]["upload_url"]))
- self.assertIsNone(self.network.getRequestBody("POST", self.PRINT_URL))
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py
deleted file mode 100644
index e24ca1694e..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from unittest import TestCase
-from unittest.mock import patch, MagicMock
-
-from UM.OutputDevice.OutputDeviceManager import OutputDeviceManager
-from cura.UltimakerCloudAuthentication import CuraCloudAPIRoot
-from ...src.Cloud import CloudApiClient
-from ...src.Cloud import CloudOutputDeviceManager
-from .Fixtures import parseFixture, readFixture
-from .NetworkManagerMock import NetworkManagerMock, FakeSignal
-
-
-class TestCloudOutputDeviceManager(TestCase):
- maxDiff = None
-
- URL = CuraCloudAPIRoot + "/connect/v1/clusters"
-
- def setUp(self):
- super().setUp()
- self.app = MagicMock()
- self.device_manager = OutputDeviceManager()
- self.app.getOutputDeviceManager.return_value = self.device_manager
-
- self.patches = [patch("UM.Qt.QtApplication.QtApplication.getInstance", return_value=self.app),
- patch("UM.Application.Application.getInstance", return_value=self.app)]
- for patched_method in self.patches:
- patched_method.start()
-
- self.network = NetworkManagerMock()
- self.timer = MagicMock(timeout = FakeSignal())
- with patch.object(CloudApiClient, "QNetworkAccessManager", return_value = self.network), \
- patch.object(CloudOutputDeviceManager, "QTimer", return_value = self.timer):
- self.manager = CloudOutputDeviceManager.CloudOutputDeviceManager()
- self.clusters_response = parseFixture("getClusters")
- self.network.prepareReply("GET", self.URL, 200, readFixture("getClusters"))
-
- def tearDown(self):
- try:
- self._beforeTearDown()
-
- self.network.flushReplies()
- self.manager.stop()
- for patched_method in self.patches:
- patched_method.stop()
- finally:
- super().tearDown()
-
- ## Before tear down method we check whether the state of the output device manager is what we expect based on the
- # mocked API response.
- def _beforeTearDown(self):
- # let the network send replies
- self.network.flushReplies()
- # get the created devices
- devices = self.device_manager.getOutputDevices()
- # TODO: Check active device
-
- response_clusters = self.clusters_response.get("data", [])
- manager_clusters = sorted([device.clusterData.toDict() for device in self.manager._remote_clusters.values()],
- key=lambda cluster: cluster['cluster_id'], reverse=True)
- self.assertEqual(response_clusters, manager_clusters)
-
- ## Runs the initial request to retrieve the clusters.
- def _loadData(self):
- self.manager.start()
- self.network.flushReplies()
-
- def test_device_is_created(self):
- # just create the cluster, it is checked at tearDown
- self._loadData()
-
- def test_device_is_updated(self):
- self._loadData()
-
- # update the cluster from member variable, which is checked at tearDown
- self.clusters_response["data"][0]["host_name"] = "New host name"
- self.network.prepareReply("GET", self.URL, 200, self.clusters_response)
-
- self.manager._update_timer.timeout.emit()
-
- def test_device_is_removed(self):
- self._loadData()
-
- # delete the cluster from member variable, which is checked at tearDown
- del self.clusters_response["data"][1]
- self.network.prepareReply("GET", self.URL, 200, self.clusters_response)
-
- self.manager._update_timer.timeout.emit()
-
- def test_device_connects_by_cluster_id(self):
- active_machine_mock = self.app.getGlobalContainerStack.return_value
- cluster1, cluster2 = self.clusters_response["data"]
- cluster_id = cluster1["cluster_id"]
- active_machine_mock.getMetaDataEntry.side_effect = {"um_cloud_cluster_id": cluster_id}.get
-
- self._loadData()
-
- self.assertTrue(self.device_manager.getOutputDevice(cluster1["cluster_id"]).isConnected())
- self.assertIsNone(self.device_manager.getOutputDevice(cluster2["cluster_id"]))
- self.assertEquals([], active_machine_mock.setMetaDataEntry.mock_calls)
-
- def test_device_connects_by_network_key(self):
- active_machine_mock = self.app.getGlobalContainerStack.return_value
-
- cluster1, cluster2 = self.clusters_response["data"]
- network_key = cluster2["host_name"] + ".ultimaker.local"
- active_machine_mock.getMetaDataEntry.side_effect = {"um_network_key": network_key}.get
-
- self._loadData()
-
- self.assertIsNone(self.device_manager.getOutputDevice(cluster1["cluster_id"]))
- self.assertTrue(self.device_manager.getOutputDevice(cluster2["cluster_id"]).isConnected())
-
- active_machine_mock.setMetaDataEntry.assert_called_with("um_cloud_cluster_id", cluster2["cluster_id"])
-
- @patch.object(CloudOutputDeviceManager, "Message")
- def test_api_error(self, message_mock):
- self.clusters_response = {
- "errors": [{"id": "notFound", "title": "Not found!", "http_status": "404", "code": "notFound"}]
- }
- self.network.prepareReply("GET", self.URL, 200, self.clusters_response)
- self._loadData()
- message_mock.return_value.show.assert_called_once_with()
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/__init__.py b/plugins/UM3NetworkPrinting/tests/Cloud/__init__.py
deleted file mode 100644
index f3f6970c54..0000000000
--- a/plugins/UM3NetworkPrinting/tests/Cloud/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/plugins/UM3NetworkPrinting/tests/TestSendMaterialJob.py b/plugins/UM3NetworkPrinting/tests/TestSendMaterialJob.py
deleted file mode 100644
index 952d38dcf4..0000000000
--- a/plugins/UM3NetworkPrinting/tests/TestSendMaterialJob.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-import io
-import json
-from unittest import TestCase, mock
-from unittest.mock import patch, call, MagicMock
-
-from PyQt5.QtCore import QByteArray
-
-from UM.Application import Application
-
-from cura.Machines.MaterialGroup import MaterialGroup
-from cura.Machines.MaterialNode import MaterialNode
-
-from ..src.SendMaterialJob import SendMaterialJob
-
-_FILES_MAP = {"generic_pla_white": "/materials/generic_pla_white.xml.fdm_material",
- "generic_pla_black": "/materials/generic_pla_black.xml.fdm_material",
- }
-
-
-@patch("builtins.open", lambda _, __: io.StringIO(""))
-class TestSendMaterialJob(TestCase):
- # version 1
- _LOCAL_MATERIAL_WHITE = {"type": "material", "status": "unknown", "id": "generic_pla_white",
- "base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
- "brand": "Generic", "material": "PLA", "color_name": "White",
- "GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "1", "color_code": "#ffffff",
- "description": "Test PLA White", "adhesion_info": "Use glue.", "approximate_diameter": "3",
- "properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
- "definition": "fdmprinter", "compatible": True}
-
- # version 2
- _LOCAL_MATERIAL_WHITE_NEWER = {"type": "material", "status": "unknown", "id": "generic_pla_white",
- "base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
- "brand": "Generic", "material": "PLA", "color_name": "White",
- "GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "2",
- "color_code": "#ffffff",
- "description": "Test PLA White", "adhesion_info": "Use glue.",
- "approximate_diameter": "3",
- "properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
- "definition": "fdmprinter", "compatible": True}
-
- # invalid version: "one"
- _LOCAL_MATERIAL_WHITE_INVALID_VERSION = {"type": "material", "status": "unknown", "id": "generic_pla_white",
- "base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
- "brand": "Generic", "material": "PLA", "color_name": "White",
- "GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "one",
- "color_code": "#ffffff",
- "description": "Test PLA White", "adhesion_info": "Use glue.",
- "approximate_diameter": "3",
- "properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
- "definition": "fdmprinter", "compatible": True}
-
- _LOCAL_MATERIAL_WHITE_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
- MaterialNode(_LOCAL_MATERIAL_WHITE))}
-
- _LOCAL_MATERIAL_WHITE_NEWER_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
- MaterialNode(_LOCAL_MATERIAL_WHITE_NEWER))}
-
- _LOCAL_MATERIAL_WHITE_INVALID_VERSION_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
- MaterialNode(_LOCAL_MATERIAL_WHITE_INVALID_VERSION))}
-
- _LOCAL_MATERIAL_BLACK = {"type": "material", "status": "unknown", "id": "generic_pla_black",
- "base_file": "generic_pla_black", "setting_version": "5", "name": "Yellow CPE",
- "brand": "Ultimaker", "material": "CPE", "color_name": "Black",
- "GUID": "5fbb362a-41f9-4818-bb43-15ea6df34aa4", "version": "1", "color_code": "#000000",
- "description": "Test PLA Black", "adhesion_info": "Use glue.", "approximate_diameter": "3",
- "properties": {"density": "1.01", "diameter": "2.85", "weight": "750"},
- "definition": "fdmprinter", "compatible": True}
-
- _LOCAL_MATERIAL_BLACK_ALL_RESULT = {"generic_pla_black": MaterialGroup("generic_pla_black",
- MaterialNode(_LOCAL_MATERIAL_BLACK))}
-
- _REMOTE_MATERIAL_WHITE = {
- "guid": "badb0ee7-87c8-4f3f-9398-938587b67dce",
- "material": "PLA",
- "brand": "Generic",
- "version": 1,
- "color": "White",
- "density": 1.00
- }
-
- _REMOTE_MATERIAL_BLACK = {
- "guid": "5fbb362a-41f9-4818-bb43-15ea6df34aa4",
- "material": "PLA",
- "brand": "Generic",
- "version": 2,
- "color": "Black",
- "density": 1.00
- }
-
- def test_run(self):
- device_mock = MagicMock()
- job = SendMaterialJob(device_mock)
- job.run()
-
- # We expect the materials endpoint to be called when the job runs.
- device_mock.get.assert_called_with("materials/", on_finished = job._onGetRemoteMaterials)
-
- def test__onGetRemoteMaterials_withFailedRequest(self):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- reply_mock.attribute.return_value = 404
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- # We expect the device not to be called for any follow up.
- self.assertEqual(0, device_mock.createFormPart.call_count)
-
- def test__onGetRemoteMaterials_withWrongEncoding(self):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- reply_mock.attribute.return_value = 200
- reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("cp500"))
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- # Given that the parsing fails we do no expect the device to be called for any follow up.
- self.assertEqual(0, device_mock.createFormPart.call_count)
-
- def test__onGetRemoteMaterials_withBadJsonAnswer(self):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- reply_mock.attribute.return_value = 200
- reply_mock.readAll.return_value = QByteArray(b"Six sick hicks nick six slick bricks with picks and sticks.")
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- # Given that the parsing fails we do no expect the device to be called for any follow up.
- self.assertEqual(0, device_mock.createFormPart.call_count)
-
- def test__onGetRemoteMaterials_withMissingGuidInRemoteMaterial(self):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- reply_mock.attribute.return_value = 200
- remote_material_without_guid = self._REMOTE_MATERIAL_WHITE.copy()
- del remote_material_without_guid["guid"]
- reply_mock.readAll.return_value = QByteArray(json.dumps([remote_material_without_guid]).encode("ascii"))
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- # Given that parsing fails we do not expect the device to be called for any follow up.
- self.assertEqual(0, device_mock.createFormPart.call_count)
-
- @patch("cura.Machines.MaterialManager.MaterialManager")
- @patch("cura.Settings.CuraContainerRegistry")
- @patch("UM.Application")
- def test__onGetRemoteMaterials_withInvalidVersionInLocalMaterial(self, application_mock, container_registry_mock,
- material_manager_mock):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- application_mock.getContainerRegistry.return_value = container_registry_mock
- application_mock.getMaterialManager.return_value = material_manager_mock
-
- reply_mock.attribute.return_value = 200
- reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
-
- material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_INVALID_VERSION_ALL_RESULT.copy()
-
- with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- self.assertEqual(0, device_mock.createFormPart.call_count)
-
- @patch("UM.Application.Application.getInstance")
- def test__onGetRemoteMaterials_withNoUpdate(self, application_mock):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- container_registry_mock = application_mock.getContainerRegistry.return_value
- material_manager_mock = application_mock.getMaterialManager.return_value
-
- device_mock.createFormPart.return_value = "_xXx_"
-
- material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_ALL_RESULT.copy()
-
- reply_mock.attribute.return_value = 200
- reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
-
- with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- self.assertEqual(0, device_mock.createFormPart.call_count)
- self.assertEqual(0, device_mock.postFormWithParts.call_count)
-
- @patch("UM.Application.Application.getInstance")
- def test__onGetRemoteMaterials_withUpdatedMaterial(self, get_instance_mock):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- application_mock = get_instance_mock.return_value
- container_registry_mock = application_mock.getContainerRegistry.return_value
- material_manager_mock = application_mock.getMaterialManager.return_value
-
- container_registry_mock.getContainerFilePathById = lambda x: _FILES_MAP.get(x)
-
- device_mock.createFormPart.return_value = "_xXx_"
-
- material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_NEWER_ALL_RESULT.copy()
-
- reply_mock.attribute.return_value = 200
- reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
-
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- self.assertEqual(1, device_mock.createFormPart.call_count)
- self.assertEqual(1, device_mock.postFormWithParts.call_count)
- self.assertEquals(
- [call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", ""),
- call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
- device_mock.method_calls)
-
- @patch("UM.Application.Application.getInstance")
- def test__onGetRemoteMaterials_withNewMaterial(self, application_mock):
- reply_mock = MagicMock()
- device_mock = MagicMock()
- container_registry_mock = application_mock.getContainerRegistry.return_value
- material_manager_mock = application_mock.getMaterialManager.return_value
-
- container_registry_mock.getContainerFilePathById = lambda x: _FILES_MAP.get(x)
-
- device_mock.createFormPart.return_value = "_xXx_"
-
- all_results = self._LOCAL_MATERIAL_WHITE_ALL_RESULT.copy()
- for key, value in self._LOCAL_MATERIAL_BLACK_ALL_RESULT.items():
- all_results[key] = value
- material_manager_mock.getAllMaterialGroups.return_value = all_results
-
- reply_mock.attribute.return_value = 200
- reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_BLACK]).encode("ascii"))
-
- with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
- job = SendMaterialJob(device_mock)
- job._onGetRemoteMaterials(reply_mock)
-
- self.assertEqual(1, device_mock.createFormPart.call_count)
- self.assertEqual(1, device_mock.postFormWithParts.call_count)
- self.assertEquals(
- [call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", ""),
- call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
- device_mock.method_calls)
diff --git a/plugins/UM3NetworkPrinting/tests/__init__.py b/plugins/UM3NetworkPrinting/tests/__init__.py
deleted file mode 100644
index f3f6970c54..0000000000
--- a/plugins/UM3NetworkPrinting/tests/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/plugins/USBPrinting/AvrFirmwareUpdater.py b/plugins/USBPrinting/AvrFirmwareUpdater.py
index 56e3f99c23..0f7146560d 100644
--- a/plugins/USBPrinting/AvrFirmwareUpdater.py
+++ b/plugins/USBPrinting/AvrFirmwareUpdater.py
@@ -13,7 +13,7 @@ from time import sleep
MYPY = False
if MYPY:
- from cura.PrinterOutputDevice import PrinterOutputDevice
+ from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
class AvrFirmwareUpdater(FirmwareUpdater):
diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py
index 3375ac27e7..c9758d88d4 100644
--- a/plugins/USBPrinting/USBPrinterOutputDevice.py
+++ b/plugins/USBPrinting/USBPrinterOutputDevice.py
@@ -1,29 +1,38 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+
import os
-from UM.Logger import Logger
from UM.i18n import i18nCatalog
+from UM.Logger import Logger
+from UM.Mesh.MeshWriter import MeshWriter #To get the g-code output.
+from UM.Message import Message #Show an error when already printing.
+from UM.PluginRegistry import PluginRegistry #To get the g-code output.
from UM.Qt.Duration import DurationFormat
from cura.CuraApplication import CuraApplication
-from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
-from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
+from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
+from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.GenericOutputController import GenericOutputController
from .AutoDetectBaudJob import AutoDetectBaudJob
from .AvrFirmwareUpdater import AvrFirmwareUpdater
+from io import StringIO #To write the g-code output.
+from queue import Queue
from serial import Serial, SerialException, SerialTimeoutException
from threading import Thread, Event
from time import time
-from queue import Queue
-from typing import Union, Optional, List, cast
+from typing import Union, Optional, List, cast, TYPE_CHECKING
import re
import functools # Used for reduce
+if TYPE_CHECKING:
+ from UM.FileHandler.FileHandler import FileHandler
+ from UM.Scene.SceneNode import SceneNode
+
catalog = i18nCatalog("cura")
@@ -52,7 +61,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._all_baud_rates = [115200, 250000, 500000, 230400, 57600, 38400, 19200, 9600]
# Instead of using a timer, we really need the update to be as a thread, as reading from serial can block.
- self._update_thread = Thread(target = self._update, daemon = True)
+ self._update_thread = Thread(target = self._update, daemon = True, name = "USBPrinterUpdate")
self._last_temperature_request = None # type: Optional[int]
self._firmware_idle_count = 0
@@ -108,34 +117,39 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
## Request the current scene to be sent to a USB-connected printer.
#
# \param nodes A collection of scene nodes to send. This is ignored.
- # \param file_name \type{string} A suggestion for a file name to write.
+ # \param file_name A suggestion for a file name to write.
# \param filter_by_machine Whether to filter MIME types by machine. This
# is ignored.
# \param kwargs Keyword arguments.
- def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs):
+ def requestWrite(self, nodes: List["SceneNode"], file_name: Optional[str] = None, limit_mimetypes: bool = False,
+ file_handler: Optional["FileHandler"] = None, filter_by_machine: bool = False, **kwargs) -> None:
if self._is_printing:
- return # Aleady printing
+ message = Message(text = catalog.i18nc("@message", "A print is still in progress. Cura cannot start another print via USB until the previous print has completed."), title = catalog.i18nc("@message", "Print in Progress"))
+ message.show()
+ return # Already printing
self.writeStarted.emit(self)
# cancel any ongoing preheat timer before starting a print
- self._printers[0].getController().stopPreheatTimers()
+ controller = cast(GenericOutputController, self._printers[0].getController())
+ controller.stopPreheatTimers()
CuraApplication.getInstance().getController().setActiveStage("MonitorStage")
- # find the G-code for the active build plate to print
- active_build_plate_id = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
- gcode_dict = getattr(CuraApplication.getInstance().getController().getScene(), "gcode_dict")
- gcode_list = gcode_dict[active_build_plate_id]
+ #Find the g-code to print.
+ gcode_textio = StringIO()
+ gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter"))
+ success = gcode_writer.write(gcode_textio, None)
+ if not success:
+ return
- self._printGCode(gcode_list)
+ self._printGCode(gcode_textio.getvalue())
## Start a print based on a g-code.
- # \param gcode_list List with gcode (strings).
- def _printGCode(self, gcode_list: List[str]):
+ # \param gcode The g-code to print.
+ def _printGCode(self, gcode: str):
self._gcode.clear()
self._paused = False
- for layer in gcode_list:
- self._gcode.extend(layer.split("\n"))
+ self._gcode.extend(gcode.split("\n"))
# Reset line number. If this is not done, first line is sometimes ignored
self._gcode.insert(0, "M110")
@@ -176,7 +190,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
try:
self._serial = Serial(str(self._serial_port), self._baud_rate, timeout=self._timeout, writeTimeout=self._timeout)
except SerialException:
- Logger.log("w", "An exception occured while trying to create serial connection")
+ Logger.log("w", "An exception occurred while trying to create serial connection")
return
CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
self._onGlobalContainerStackChanged()
@@ -198,7 +212,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._serial.close()
# Re-create the thread so it can be started again later.
- self._update_thread = Thread(target=self._update, daemon=True)
+ self._update_thread = Thread(target=self._update, daemon=True, name = "USBPrinterUpdate")
self._serial = None
## Send a command to printer.
@@ -221,6 +235,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
except SerialTimeoutException:
Logger.log("w", "Timeout when sending command to printer via USB.")
self._command_received.set()
+ except SerialException:
+ Logger.logException("w", "An unexpected exception occurred while writing to the serial.")
+ self.setConnectionState(ConnectionState.Error)
def _update(self):
while self._connection_state == ConnectionState.Connected and self._serial is not None:
@@ -311,7 +328,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
def _setFirmwareName(self, name):
new_name = re.findall(r"FIRMWARE_NAME:(.*);", str(name))
- if new_name:
+ if new_name:
self._firmware_name = new_name[0]
Logger.log("i", "USB output device Firmware name: %s", self._firmware_name)
else:
@@ -366,10 +383,17 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
- progress = (self._gcode_position / len(self._gcode))
+ print_job = self._printers[0].activePrintJob
+ try:
+ progress = self._gcode_position / len(self._gcode)
+ except ZeroDivisionError:
+ # There is nothing to send!
+ if print_job is not None:
+ print_job.updateState("error")
+ return
elapsed_time = int(time() - self._print_start_time)
- print_job = self._printers[0].activePrintJob
+
if print_job is None:
controller = GenericOutputController(self)
controller.setCanUpdateFirmware(True)
diff --git a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py
index d4c0d1828e..56f53145b0 100644
--- a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py
+++ b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py
@@ -4,16 +4,16 @@
import threading
import time
import serial.tools.list_ports
+from os import environ
+from re import search
-from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
+from PyQt5.QtCore import QObject, pyqtSignal
-from UM.Logger import Logger
from UM.Signal import Signal, signalemitter
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.i18n import i18nCatalog
-from cura.PrinterOutputDevice import ConnectionState
-from cura.CuraApplication import CuraApplication
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionState
from . import USBPrinterOutputDevice
@@ -114,6 +114,27 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
port = (port.device, port.description, port.hwid)
if only_list_usb and not port[2].startswith("USB"):
continue
+
+ # To prevent cura from messing with serial ports of other devices,
+ # filter by regular expressions passed in as environment variables.
+ # Get possible patterns with python3 -m serial.tools.list_ports -v
+
+ # set CURA_DEVICENAMES=USB[1-9] -> e.g. not matching /dev/ttyUSB0
+ pattern = environ.get('CURA_DEVICENAMES')
+ if pattern and not search(pattern, port[0]):
+ continue
+
+ # set CURA_DEVICETYPES=CP2102 -> match a type of serial converter
+ pattern = environ.get('CURA_DEVICETYPES')
+ if pattern and not search(pattern, port[1]):
+ continue
+
+ # set CURA_DEVICEINFOS=LOCATION=2-1.4 -> match a physical port
+ # set CURA_DEVICEINFOS=VID:PID=10C4:EA60 -> match a vendor:product
+ pattern = environ.get('CURA_DEVICEINFOS')
+ if pattern and not search(pattern, port[2]):
+ continue
+
base_list += [port[0]]
return list(base_list)
diff --git a/plugins/USBPrinting/plugin.json b/plugins/USBPrinting/plugin.json
index 45971d858b..c05ea65f2d 100644
--- a/plugins/USBPrinting/plugin.json
+++ b/plugins/USBPrinting/plugin.json
@@ -2,7 +2,7 @@
"name": "USB printing",
"author": "Ultimaker B.V.",
"version": "1.0.2",
- "api": "6.0",
+ "api": "7.0",
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
"i18n-catalog": "cura"
}
diff --git a/plugins/UltimakerMachineActions/BedLevelMachineAction.py b/plugins/UltimakerMachineActions/BedLevelMachineAction.py
index d6de21c89b..818ad0e4f0 100644
--- a/plugins/UltimakerMachineActions/BedLevelMachineAction.py
+++ b/plugins/UltimakerMachineActions/BedLevelMachineAction.py
@@ -4,7 +4,7 @@
from typing import List
from cura.MachineAction import MachineAction
-from cura.PrinterOutputDevice import PrinterOutputDevice
+from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from UM.FlameProfiler import pyqtSlot
diff --git a/plugins/UltimakerMachineActions/BedLevelMachineAction.qml b/plugins/UltimakerMachineActions/BedLevelMachineAction.qml
index 262d5df376..a9f7e93d44 100644
--- a/plugins/UltimakerMachineActions/BedLevelMachineAction.qml
+++ b/plugins/UltimakerMachineActions/BedLevelMachineAction.qml
@@ -1,24 +1,27 @@
-// Copyright (c) 2016 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
-import UM 1.2 as UM
-import Cura 1.0 as Cura
+import UM 1.3 as UM
+import Cura 1.1 as Cura
Cura.MachineAction
{
- anchors.fill: parent;
+ UM.I18nCatalog { id: catalog; name: "cura"; }
+
+ anchors.fill: parent
+
Item
{
id: bedLevelMachineAction
- anchors.fill: parent;
-
- UM.I18nCatalog { id: catalog; name: "cura"; }
+ anchors.top: parent.top
+ anchors.topMargin: UM.Theme.getSize("default_margin").height * 3
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width * 3 / 4
Label
{
@@ -26,17 +29,24 @@ Cura.MachineAction
width: parent.width
text: catalog.i18nc("@title", "Build Plate Leveling")
wrapMode: Text.WordWrap
- font.pointSize: 18;
+ font: UM.Theme.getFont("medium")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
+
Label
{
id: pageDescription
anchors.top: pageTitle.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
+ anchors.topMargin: UM.Theme.getSize("default_margin").height * 3
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted.")
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
+
Label
{
id: bedlevelingText
@@ -45,37 +55,40 @@ Cura.MachineAction
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle.")
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
Row
{
id: bedlevelingWrapper
anchors.top: bedlevelingText.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
+ anchors.topMargin: UM.Theme.getSize("default_margin").height * 3
anchors.horizontalCenter: parent.horizontalCenter
width: childrenRect.width
spacing: UM.Theme.getSize("default_margin").width
- Button
+ Cura.ActionButton
{
id: startBedLevelingButton
- text: catalog.i18nc("@action:button","Start Build Plate Leveling")
+ text: catalog.i18nc("@action:button", "Start Build Plate Leveling")
onClicked:
{
- startBedLevelingButton.visible = false;
- bedlevelingButton.visible = true;
- manager.startBedLeveling();
+ startBedLevelingButton.visible = false
+ bedlevelingButton.visible = true
+ manager.startBedLeveling()
}
}
- Button
+ Cura.ActionButton
{
id: bedlevelingButton
- text: catalog.i18nc("@action:button","Move to Next Position")
+ text: catalog.i18nc("@action:button", "Move to Next Position")
visible: false
onClicked:
{
- manager.moveToNextLevelPosition();
+ manager.moveToNextLevelPosition()
}
}
}
diff --git a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py b/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
deleted file mode 100644
index 6ff3f0b629..0000000000
--- a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Uranium is released under the terms of the LGPLv3 or higher.
-
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from cura.MachineAction import MachineAction
-from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
-
-from UM.i18n import i18nCatalog
-from UM.Application import Application
-from UM.Util import parseBool
-catalog = i18nCatalog("cura")
-
-
-## The Ultimaker 2 can have a few revisions & upgrades.
-class UM2UpgradeSelection(MachineAction):
- def __init__(self):
- super().__init__("UM2UpgradeSelection", catalog.i18nc("@action", "Select upgrades"))
- self._qml_url = "UM2UpgradeSelectionMachineAction.qml"
-
- self._container_registry = ContainerRegistry.getInstance()
-
- self._current_global_stack = None
-
- Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
- self._reset()
-
- def _reset(self):
- self.hasVariantsChanged.emit()
-
- def _onGlobalStackChanged(self):
- if self._current_global_stack:
- self._current_global_stack.metaDataChanged.disconnect(self._onGlobalStackMetaDataChanged)
-
- self._current_global_stack = Application.getInstance().getGlobalContainerStack()
- if self._current_global_stack:
- self._current_global_stack.metaDataChanged.connect(self._onGlobalStackMetaDataChanged)
- self._reset()
-
- def _onGlobalStackMetaDataChanged(self):
- self._reset()
-
- hasVariantsChanged = pyqtSignal()
-
- def setHasVariants(self, has_variants = True):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack:
- variant_container = global_container_stack.extruders["0"].variant
-
- if has_variants:
- global_container_stack.setMetaDataEntry("has_variants", True)
-
- # Set the variant container to a sane default
- empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer()
- if type(variant_container) == type(empty_container):
- search_criteria = { "type": "variant", "definition": "ultimaker2", "id": "*0.4*" }
- containers = self._container_registry.findInstanceContainers(**search_criteria)
- if containers:
- global_container_stack.extruders["0"].variant = containers[0]
- else:
- # The metadata entry is stored in an ini, and ini files are parsed as strings only.
- # Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
- if "has_variants" in global_container_stack.getMetaData():
- global_container_stack.removeMetaDataEntry("has_variants")
-
- # Set the variant container to an empty variant
- global_container_stack.extruders["0"].variant = ContainerRegistry.getInstance().getEmptyInstanceContainer()
-
- Application.getInstance().globalContainerStackChanged.emit()
- self._reset()
-
- @pyqtProperty(bool, fset = setHasVariants, notify = hasVariantsChanged)
- def hasVariants(self):
- if self._current_global_stack:
- return parseBool(self._current_global_stack.getMetaDataEntry("has_variants", "false"))
diff --git a/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml b/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
deleted file mode 100644
index 793f3f00a8..0000000000
--- a/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2016 Ultimaker B.V.
-// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
-
-import UM 1.2 as UM
-import Cura 1.0 as Cura
-
-
-Cura.MachineAction
-{
- anchors.fill: parent;
-
- Item
- {
- id: upgradeSelectionMachineAction
- anchors.fill: parent
-
- Label
- {
- id: pageTitle
- width: parent.width
- text: catalog.i18nc("@title", "Select Printer Upgrades")
- wrapMode: Text.WordWrap
- font.pointSize: 18;
- }
-
- Label
- {
- id: pageDescription
- anchors.top: pageTitle.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- width: parent.width
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker 2.");
- }
-
- CheckBox
- {
- id: olssonBlockCheckBox
- anchors.top: pageDescription.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
-
- text: catalog.i18nc("@label", "Olsson Block")
- checked: manager.hasVariants
- onClicked: manager.hasVariants = checked
-
- Connections
- {
- target: manager
- onHasVariantsChanged: olssonBlockCheckBox.checked = manager.hasVariants
- }
- }
-
- UM.I18nCatalog { id: catalog; name: "cura"; }
- }
-}
\ No newline at end of file
diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py
deleted file mode 100644
index f9ad4789e5..0000000000
--- a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py
+++ /dev/null
@@ -1,193 +0,0 @@
-from cura.MachineAction import MachineAction
-from cura.PrinterOutputDevice import PrinterOutputDevice
-from UM.Application import Application
-from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
-
-from UM.Logger import Logger
-from UM.i18n import i18nCatalog
-catalog = i18nCatalog("cura")
-
-
-## Action to check up if the self-built UMO was done correctly.
-class UMOCheckupMachineAction(MachineAction):
- def __init__(self):
- super().__init__("UMOCheckup", catalog.i18nc("@action", "Checkup"))
- self._qml_url = "UMOCheckupMachineAction.qml"
- self._hotend_target_temp = 180
- self._bed_target_temp = 60
- self._output_device = None
- self._bed_test_completed = False
- self._hotend_test_completed = False
-
- # Endstop tests
- self._x_min_endstop_test_completed = False
- self._y_min_endstop_test_completed = False
- self._z_min_endstop_test_completed = False
-
- self._check_started = False
-
- Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
-
- onBedTestCompleted = pyqtSignal()
- onHotendTestCompleted = pyqtSignal()
-
- onXMinEndstopTestCompleted = pyqtSignal()
- onYMinEndstopTestCompleted = pyqtSignal()
- onZMinEndstopTestCompleted = pyqtSignal()
-
- bedTemperatureChanged = pyqtSignal()
- hotendTemperatureChanged = pyqtSignal()
-
- def _onOutputDevicesChanged(self):
- # Check if this action was started, but no output device was found the first time.
- # If so, re-try now that an output device has been added/removed.
- if self._output_device is None and self._check_started:
- self.startCheck()
-
- def _getPrinterOutputDevices(self):
- return [printer_output_device for printer_output_device in
- Application.getInstance().getOutputDeviceManager().getOutputDevices() if
- isinstance(printer_output_device, PrinterOutputDevice)]
-
- def _reset(self):
- if self._output_device:
- self._output_device.bedTemperatureChanged.disconnect(self.bedTemperatureChanged)
- self._output_device.hotendTemperaturesChanged.disconnect(self.hotendTemperatureChanged)
- self._output_device.bedTemperatureChanged.disconnect(self._onBedTemperatureChanged)
- self._output_device.hotendTemperaturesChanged.disconnect(self._onHotendTemperatureChanged)
- self._output_device.endstopStateChanged.disconnect(self._onEndstopStateChanged)
- try:
- self._output_device.stopPollEndstop()
- except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
- Logger.log("e", "An exception occurred while stopping end stop polling: %s" % str(e))
-
- self._output_device = None
-
- self._check_started = False
- self.checkStartedChanged.emit()
-
- # Ensure everything is reset (and right signals are emitted again)
- self._bed_test_completed = False
- self.onBedTestCompleted.emit()
- self._hotend_test_completed = False
- self.onHotendTestCompleted.emit()
-
- self._x_min_endstop_test_completed = False
- self.onXMinEndstopTestCompleted.emit()
- self._y_min_endstop_test_completed = False
- self.onYMinEndstopTestCompleted.emit()
- self._z_min_endstop_test_completed = False
- self.onZMinEndstopTestCompleted.emit()
-
- self.heatedBedChanged.emit()
-
- @pyqtProperty(bool, notify = onBedTestCompleted)
- def bedTestCompleted(self):
- return self._bed_test_completed
-
- @pyqtProperty(bool, notify = onHotendTestCompleted)
- def hotendTestCompleted(self):
- return self._hotend_test_completed
-
- @pyqtProperty(bool, notify = onXMinEndstopTestCompleted)
- def xMinEndstopTestCompleted(self):
- return self._x_min_endstop_test_completed
-
- @pyqtProperty(bool, notify=onYMinEndstopTestCompleted)
- def yMinEndstopTestCompleted(self):
- return self._y_min_endstop_test_completed
-
- @pyqtProperty(bool, notify=onZMinEndstopTestCompleted)
- def zMinEndstopTestCompleted(self):
- return self._z_min_endstop_test_completed
-
- @pyqtProperty(float, notify = bedTemperatureChanged)
- def bedTemperature(self):
- if not self._output_device:
- return 0
- return self._output_device.bedTemperature
-
- @pyqtProperty(float, notify=hotendTemperatureChanged)
- def hotendTemperature(self):
- if not self._output_device:
- return 0
- return self._output_device.hotendTemperatures[0]
-
- def _onHotendTemperatureChanged(self):
- if not self._output_device:
- return
- if not self._hotend_test_completed:
- if self._output_device.hotendTemperatures[0] + 10 > self._hotend_target_temp and self._output_device.hotendTemperatures[0] - 10 < self._hotend_target_temp:
- self._hotend_test_completed = True
- self.onHotendTestCompleted.emit()
-
- def _onBedTemperatureChanged(self):
- if not self._output_device:
- return
- if not self._bed_test_completed:
- if self._output_device.bedTemperature + 5 > self._bed_target_temp and self._output_device.bedTemperature - 5 < self._bed_target_temp:
- self._bed_test_completed = True
- self.onBedTestCompleted.emit()
-
- def _onEndstopStateChanged(self, switch_type, state):
- if state:
- if switch_type == "x_min":
- self._x_min_endstop_test_completed = True
- self.onXMinEndstopTestCompleted.emit()
- elif switch_type == "y_min":
- self._y_min_endstop_test_completed = True
- self.onYMinEndstopTestCompleted.emit()
- elif switch_type == "z_min":
- self._z_min_endstop_test_completed = True
- self.onZMinEndstopTestCompleted.emit()
-
- checkStartedChanged = pyqtSignal()
-
- @pyqtProperty(bool, notify = checkStartedChanged)
- def checkStarted(self):
- return self._check_started
-
- @pyqtSlot()
- def startCheck(self):
- self._check_started = True
- self.checkStartedChanged.emit()
- output_devices = self._getPrinterOutputDevices()
- if output_devices:
- self._output_device = output_devices[0]
- try:
- self._output_device.sendCommand("M18") # Turn off all motors so the user can move the axes
- self._output_device.startPollEndstop()
- self._output_device.bedTemperatureChanged.connect(self.bedTemperatureChanged)
- self._output_device.hotendTemperaturesChanged.connect(self.hotendTemperatureChanged)
- self._output_device.bedTemperatureChanged.connect(self._onBedTemperatureChanged)
- self._output_device.hotendTemperaturesChanged.connect(self._onHotendTemperatureChanged)
- self._output_device.endstopStateChanged.connect(self._onEndstopStateChanged)
- except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
- Logger.log("e", "An exception occurred while starting end stop polling: %s" % str(e))
-
- @pyqtSlot()
- def cooldownHotend(self):
- if self._output_device is not None:
- self._output_device.setTargetHotendTemperature(0, 0)
-
- @pyqtSlot()
- def cooldownBed(self):
- if self._output_device is not None:
- self._output_device.setTargetBedTemperature(0)
-
- @pyqtSlot()
- def heatupHotend(self):
- if self._output_device is not None:
- self._output_device.setTargetHotendTemperature(0, self._hotend_target_temp)
-
- @pyqtSlot()
- def heatupBed(self):
- if self._output_device is not None:
- self._output_device.setTargetBedTemperature(self._bed_target_temp)
-
- heatedBedChanged = pyqtSignal()
-
- @pyqtProperty(bool, notify = heatedBedChanged)
- def hasHeatedBed(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- return global_container_stack.getProperty("machine_heated_bed", "value")
\ No newline at end of file
diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml
deleted file mode 100644
index 2a01cfaa40..0000000000
--- a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml
+++ /dev/null
@@ -1,288 +0,0 @@
-import UM 1.2 as UM
-import Cura 1.0 as Cura
-
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
-
-Cura.MachineAction
-{
- anchors.fill: parent;
- Item
- {
- id: checkupMachineAction
- anchors.fill: parent;
- property int leftRow: (checkupMachineAction.width * 0.40) | 0
- property int rightRow: (checkupMachineAction.width * 0.60) | 0
- property bool heatupHotendStarted: false
- property bool heatupBedStarted: false
- property bool printerConnected: Cura.MachineManager.printerConnected
-
- UM.I18nCatalog { id: catalog; name: "cura"}
- Label
- {
- id: pageTitle
- width: parent.width
- text: catalog.i18nc("@title", "Check Printer")
- wrapMode: Text.WordWrap
- font.pointSize: 18;
- }
-
- Label
- {
- id: pageDescription
- anchors.top: pageTitle.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- width: parent.width
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label", "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional");
- }
-
- Row
- {
- id: startStopButtons
- anchors.top: pageDescription.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- anchors.horizontalCenter: parent.horizontalCenter
- width: childrenRect.width
- spacing: UM.Theme.getSize("default_margin").width
- Button
- {
- id: startCheckButton
- text: catalog.i18nc("@action:button","Start Printer Check");
- onClicked:
- {
- checkupMachineAction.heatupHotendStarted = false;
- checkupMachineAction.heatupBedStarted = false;
- manager.startCheck();
- startCheckButton.visible = false;
- }
- }
- }
-
- Item
- {
- id: checkupContent
- anchors.top: startStopButtons.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- visible: manager.checkStarted
- width: parent.width
- height: 250
- //////////////////////////////////////////////////////////
- Label
- {
- id: connectionLabel
- width: checkupMachineAction.leftRow
- anchors.left: parent.left
- anchors.top: parent.top
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Connection: ")
- }
- Label
- {
- id: connectionStatus
- width: checkupMachineAction.rightRow
- anchors.left: connectionLabel.right
- anchors.top: parent.top
- wrapMode: Text.WordWrap
- text: checkupMachineAction.printerConnected ? catalog.i18nc("@info:status","Connected"): catalog.i18nc("@info:status","Not connected")
- }
- //////////////////////////////////////////////////////////
- Label
- {
- id: endstopXLabel
- width: checkupMachineAction.leftRow
- anchors.left: parent.left
- anchors.top: connectionLabel.bottom
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Min endstop X: ")
- visible: checkupMachineAction.printerConnected
- }
- Label
- {
- id: endstopXStatus
- width: checkupMachineAction.rightRow
- anchors.left: endstopXLabel.right
- anchors.top: connectionLabel.bottom
- wrapMode: Text.WordWrap
- text: manager.xMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
- visible: checkupMachineAction.printerConnected
- }
- //////////////////////////////////////////////////////////////
- Label
- {
- id: endstopYLabel
- width: checkupMachineAction.leftRow
- anchors.left: parent.left
- anchors.top: endstopXLabel.bottom
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Min endstop Y: ")
- visible: checkupMachineAction.printerConnected
- }
- Label
- {
- id: endstopYStatus
- width: checkupMachineAction.rightRow
- anchors.left: endstopYLabel.right
- anchors.top: endstopXLabel.bottom
- wrapMode: Text.WordWrap
- text: manager.yMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
- visible: checkupMachineAction.printerConnected
- }
- /////////////////////////////////////////////////////////////////////
- Label
- {
- id: endstopZLabel
- width: checkupMachineAction.leftRow
- anchors.left: parent.left
- anchors.top: endstopYLabel.bottom
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Min endstop Z: ")
- visible: checkupMachineAction.printerConnected
- }
- Label
- {
- id: endstopZStatus
- width: checkupMachineAction.rightRow
- anchors.left: endstopZLabel.right
- anchors.top: endstopYLabel.bottom
- wrapMode: Text.WordWrap
- text: manager.zMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
- visible: checkupMachineAction.printerConnected
- }
- ////////////////////////////////////////////////////////////
- Label
- {
- id: nozzleTempLabel
- width: checkupMachineAction.leftRow
- height: nozzleTempButton.height
- anchors.left: parent.left
- anchors.top: endstopZLabel.bottom
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Nozzle temperature check: ")
- visible: checkupMachineAction.printerConnected
- }
- Label
- {
- id: nozzleTempStatus
- width: (checkupMachineAction.rightRow * 0.4) | 0
- anchors.top: nozzleTempLabel.top
- anchors.left: nozzleTempLabel.right
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@info:status","Not checked")
- visible: checkupMachineAction.printerConnected
- }
- Item
- {
- id: nozzleTempButton
- width: (checkupMachineAction.rightRow * 0.3) | 0
- height: childrenRect.height
- anchors.top: nozzleTempLabel.top
- anchors.left: bedTempStatus.right
- anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width/2)
- visible: checkupMachineAction.printerConnected
- Button
- {
- text: checkupMachineAction.heatupHotendStarted ? catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating")
- onClicked:
- {
- if (checkupMachineAction.heatupHotendStarted)
- {
- manager.cooldownHotend()
- checkupMachineAction.heatupHotendStarted = false
- } else
- {
- manager.heatupHotend()
- checkupMachineAction.heatupHotendStarted = true
- }
- }
- }
- }
- Label
- {
- id: nozzleTemp
- anchors.top: nozzleTempLabel.top
- anchors.left: nozzleTempButton.right
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- width: (checkupMachineAction.rightRow * 0.2) | 0
- wrapMode: Text.WordWrap
- text: manager.hotendTemperature + "°C"
- font.bold: true
- visible: checkupMachineAction.printerConnected
- }
- /////////////////////////////////////////////////////////////////////////////
- Label
- {
- id: bedTempLabel
- width: checkupMachineAction.leftRow
- height: bedTempButton.height
- anchors.left: parent.left
- anchors.top: nozzleTempLabel.bottom
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Build plate temperature check:")
- visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
- }
-
- Label
- {
- id: bedTempStatus
- width: (checkupMachineAction.rightRow * 0.4) | 0
- anchors.top: bedTempLabel.top
- anchors.left: bedTempLabel.right
- wrapMode: Text.WordWrap
- text: manager.bedTestCompleted ? catalog.i18nc("@info:status","Not checked"): catalog.i18nc("@info:status","Checked")
- visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
- }
- Item
- {
- id: bedTempButton
- width: (checkupMachineAction.rightRow * 0.3) | 0
- height: childrenRect.height
- anchors.top: bedTempLabel.top
- anchors.left: bedTempStatus.right
- anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width/2)
- visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
- Button
- {
- text: checkupMachineAction.heatupBedStarted ?catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating")
- onClicked:
- {
- if (checkupMachineAction.heatupBedStarted)
- {
- manager.cooldownBed()
- checkupMachineAction.heatupBedStarted = false
- } else
- {
- manager.heatupBed()
- checkupMachineAction.heatupBedStarted = true
- }
- }
- }
- }
- Label
- {
- id: bedTemp
- width: (checkupMachineAction.rightRow * 0.2) | 0
- anchors.top: bedTempLabel.top
- anchors.left: bedTempButton.right
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- wrapMode: Text.WordWrap
- text: manager.bedTemperature + "°C"
- font.bold: true
- visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
- }
- Label
- {
- id: resultText
- visible: false
- anchors.top: bedTemp.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- anchors.left: parent.left
- width: parent.width
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label", "Everything is in order! You're done with your CheckUp.")
- }
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml b/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml
index 2b973ca1bb..565ba2fa0e 100644
--- a/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml
+++ b/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml
@@ -1,43 +1,39 @@
-// Copyright (c) 2016 Ultimaker B.V.
+// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
+import QtQuick 2.10
+import QtQuick.Controls 2.3
-import UM 1.2 as UM
-import Cura 1.0 as Cura
+import UM 1.3 as UM
+import Cura 1.1 as Cura
Cura.MachineAction
{
- anchors.fill: parent;
+ UM.I18nCatalog { id: catalog; name: "cura"; }
+ anchors.fill: parent
+
Item
{
id: upgradeSelectionMachineAction
anchors.fill: parent
-
- Label
- {
- id: pageTitle
- width: parent.width
- text: catalog.i18nc("@title", "Select Printer Upgrades")
- wrapMode: Text.WordWrap
- font.pointSize: 18;
- }
+ anchors.topMargin: UM.Theme.getSize("default_margin").width * 5
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width * 4
Label
{
id: pageDescription
- anchors.top: pageTitle.bottom
+ anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
wrapMode: Text.WordWrap
- text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker Original");
+ text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker Original")
+ font: UM.Theme.getFont("medium")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
- CheckBox
+ Cura.CheckBox
{
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
@@ -46,7 +42,5 @@ Cura.MachineAction
checked: manager.hasHeatedBed
onClicked: manager.setHeatedBed(checked)
}
-
- UM.I18nCatalog { id: catalog; name: "cura"; }
}
-}
\ No newline at end of file
+}
diff --git a/plugins/UltimakerMachineActions/__init__.py b/plugins/UltimakerMachineActions/__init__.py
index e87949580a..aecb3b0ad6 100644
--- a/plugins/UltimakerMachineActions/__init__.py
+++ b/plugins/UltimakerMachineActions/__init__.py
@@ -1,9 +1,8 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import BedLevelMachineAction
from . import UMOUpgradeSelection
-from . import UM2UpgradeSelection
def getMetaData():
return {}
@@ -11,6 +10,5 @@ def getMetaData():
def register(app):
return { "machine_action": [
BedLevelMachineAction.BedLevelMachineAction(),
- UMOUpgradeSelection.UMOUpgradeSelection(),
- UM2UpgradeSelection.UM2UpgradeSelection()
+ UMOUpgradeSelection.UMOUpgradeSelection()
]}
diff --git a/plugins/UltimakerMachineActions/plugin.json b/plugins/UltimakerMachineActions/plugin.json
index 3e3e0af9b0..e33d77c154 100644
--- a/plugins/UltimakerMachineActions/plugin.json
+++ b/plugins/UltimakerMachineActions/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/UserAgreement/UserAgreement.py b/plugins/UserAgreement/UserAgreement.py
deleted file mode 100644
index 4ea1ccf9bb..0000000000
--- a/plugins/UserAgreement/UserAgreement.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-import os
-
-from PyQt5.QtCore import QObject, pyqtSlot
-
-from UM.Extension import Extension
-from UM.Logger import Logger
-
-
-class UserAgreement(QObject, Extension):
- def __init__(self, application):
- super(UserAgreement, self).__init__()
- self._application = application
- self._user_agreement_window = None
- self._user_agreement_context = None
- self._application.engineCreatedSignal.connect(self._onEngineCreated)
-
- self._application.getPreferences().addPreference("general/accepted_user_agreement", False)
-
- def _onEngineCreated(self):
- if not self._application.getPreferences().getValue("general/accepted_user_agreement"):
- self.showUserAgreement()
-
- def showUserAgreement(self):
- if not self._user_agreement_window:
- self.createUserAgreementWindow()
-
- self._user_agreement_window.show()
-
- @pyqtSlot(bool)
- def didAgree(self, user_choice):
- if user_choice:
- Logger.log("i", "User agreed to the user agreement")
- self._application.getPreferences().setValue("general/accepted_user_agreement", True)
- self._user_agreement_window.hide()
- else:
- Logger.log("i", "User did NOT agree to the user agreement")
- self._application.getPreferences().setValue("general/accepted_user_agreement", False)
- self._application.quit()
- self._application.setNeedToShowUserAgreement(False)
-
- def createUserAgreementWindow(self):
- path = os.path.join(self._application.getPluginRegistry().getPluginPath(self.getPluginId()), "UserAgreement.qml")
- self._user_agreement_window = self._application.createQmlComponent(path, {"manager": self})
diff --git a/plugins/UserAgreement/UserAgreement.qml b/plugins/UserAgreement/UserAgreement.qml
deleted file mode 100644
index 2e5893fc41..0000000000
--- a/plugins/UserAgreement/UserAgreement.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2017 Ultimaker B.V.
-// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.2
-import QtQuick.Controls 1.4
-
-import UM 1.3 as UM
-
-UM.Dialog
-{
- id: baseDialog
- minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width * 0.75)
- minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height * 0.5)
- width: minimumWidth
- height: minimumHeight
- title: catalog.i18nc("@title:window", "User Agreement")
-
- TextArea
- {
- anchors.top: parent.top
- width: parent.width
- anchors.bottom: buttonRow.top
- text: '
DISCLAIMER BY ULTIMAKER
-
PLEASE READ THIS DISCLAIMER CAREFULLY.
-
EXCEPT WHEN OTHERWISE STATED IN WRITING, ULTIMAKER PROVIDES ANY ULTIMAKER SOFTWARE OR THIRD PARTY SOFTWARE “AS IS” WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF ULTIMAKER SOFTWARE IS WITH YOU.
-
UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, IN NO EVENT WILL ULTIMAKER BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE ANY ULTIMAKER SOFTWARE OR THIRD PARTY SOFTWARE.
- '
- readOnly: true;
- textFormat: TextEdit.RichText
- }
-
- Item
- {
- id: buttonRow
- anchors.bottom: parent.bottom
- width: parent.width
- anchors.bottomMargin: UM.Theme.getSize("default_margin").height
-
- UM.I18nCatalog { id: catalog; name: "cura" }
-
- Button
- {
- anchors.right: parent.right
- text: catalog.i18nc("@action:button", "I understand and agree")
- onClicked: {
- baseDialog.accepted()
- }
- }
-
- Button
- {
- anchors.left: parent.left
- text: catalog.i18nc("@action:button", "I don't agree")
- onClicked: {
- baseDialog.rejected()
- }
- }
- }
-
- onAccepted: manager.didAgree(true)
- onRejected: manager.didAgree(false)
- onClosing: manager.didAgree(false)
-}
diff --git a/plugins/UserAgreement/__init__.py b/plugins/UserAgreement/__init__.py
deleted file mode 100644
index 3cf81c64f4..0000000000
--- a/plugins/UserAgreement/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from . import UserAgreement
-
-def getMetaData():
- return {}
-
-def register(app):
- return {"extension": UserAgreement.UserAgreement(app)}
diff --git a/plugins/UserAgreement/plugin.json b/plugins/UserAgreement/plugin.json
deleted file mode 100644
index b172d1f9a2..0000000000
--- a/plugins/UserAgreement/plugin.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "UserAgreement",
- "author": "Ultimaker B.V.",
- "version": "1.0.1",
- "description": "Ask the user once if he/she agrees with our license.",
- "api": "6.0",
- "i18n-catalog": "cura"
-}
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py
index af9635d384..8419b3beeb 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py
@@ -6,7 +6,7 @@ import io #To write config files to strings as if they were files.
from typing import Dict, List, Optional, Tuple
import UM.VersionUpgrade
-from UM.Logger import Logger
+
## Creates a new profile instance by parsing a serialised profile in version 1
# of the file format.
@@ -20,6 +20,7 @@ def importFrom(serialised: str, filename: str) -> Optional["Profile"]:
except (configparser.Error, UM.VersionUpgrade.FormatException, UM.VersionUpgrade.InvalidVersionException):
return None
+
## A representation of a profile used as intermediary form for conversion from
# one format to the other.
class Profile:
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json
index cad94c2eb5..547c1f9f4e 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json
index 7da1e7a56d..51e3cd6794 100644
--- a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json
index e1f0a47685..4a2c04ad8e 100644
--- a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/tests/TestVersionUpgrade25to26.py b/plugins/VersionUpgrade/VersionUpgrade25to26/tests/TestVersionUpgrade25to26.py
index 9d7c7646cc..45cdaebe87 100644
--- a/plugins/VersionUpgrade/VersionUpgrade25to26/tests/TestVersionUpgrade25to26.py
+++ b/plugins/VersionUpgrade/VersionUpgrade25to26/tests/TestVersionUpgrade25to26.py
@@ -1,5 +1,8 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+import os.path
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import configparser #To check whether the appropriate exceptions are raised.
import pytest #To register tests with.
diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json
index 6cdbd64cbb..a72c5210f9 100644
--- a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py b/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py
index eebaca23c6..6235578238 100644
--- a/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py
+++ b/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py
@@ -3,7 +3,9 @@
import configparser #To check whether the appropriate exceptions are raised.
import pytest #To register tests with.
-
+import os.path
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import VersionUpgrade26to27 #The module we're testing.
## Creates an instance of the upgrader to test with.
diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json
index 885d741a8c..787d03fdf3 100644
--- a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/tests/TestVersionUpgrade27to30.py b/plugins/VersionUpgrade/VersionUpgrade27to30/tests/TestVersionUpgrade27to30.py
index cae08ebcfd..8ac6616511 100644
--- a/plugins/VersionUpgrade/VersionUpgrade27to30/tests/TestVersionUpgrade27to30.py
+++ b/plugins/VersionUpgrade/VersionUpgrade27to30/tests/TestVersionUpgrade27to30.py
@@ -1,6 +1,8 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-
+import os.path
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import configparser #To parse the resulting config files.
import pytest #To register tests with.
diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json
index d5f22649c1..7303d576cc 100644
--- a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
index eb489169e0..a6f8f743e6 100644
--- a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json
index 9649010643..4f8c7b0a94 100644
--- a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json b/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json
index 71b13ee5a9..bdcb6598d1 100644
--- a/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 3.4 to Cura 3.5.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade34to35/tests/TestVersionUpgrade34to35.py b/plugins/VersionUpgrade/VersionUpgrade34to35/tests/TestVersionUpgrade34to35.py
index b74e6f35ac..9f306e74fa 100644
--- a/plugins/VersionUpgrade/VersionUpgrade34to35/tests/TestVersionUpgrade34to35.py
+++ b/plugins/VersionUpgrade/VersionUpgrade34to35/tests/TestVersionUpgrade34to35.py
@@ -1,6 +1,8 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-
+import os.path
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import configparser #To parse the resulting config files.
import pytest #To register tests with.
diff --git a/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py b/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py
index 900c0a7396..71ce2e4fd0 100644
--- a/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py
+++ b/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py
@@ -3,7 +3,7 @@ from typing import Tuple, List, Set, Dict
import io
from UM.VersionUpgrade import VersionUpgrade
-from cura.PrinterOutputDevice import ConnectionType
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
deleted_settings = {"bridge_wall_max_overhang"} # type: Set[str]
renamed_configurations = {"connect_group_name": "group_name"} # type: Dict[str, str]
diff --git a/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json b/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json
index 578594fb6d..68259c1b9c 100644
--- a/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Upgrades configurations from Cura 3.5 to Cura 4.0.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py
index d80e0007aa..b63d1842b7 100644
--- a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py
+++ b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py
@@ -1,8 +1,9 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser
import io
+import uuid
from typing import Dict, List, Tuple
from UM.VersionUpgrade import VersionUpgrade
@@ -18,6 +19,7 @@ _renamed_quality_profiles = {
"gmax15plus_pla_very_thick": "gmax15plus_global_very_thick"
} # type: Dict[str, str]
+
## Upgrades configurations from the state they were in at version 4.0 to the
# state they should be in at version 4.1.
class VersionUpgrade40to41(VersionUpgrade):
@@ -49,6 +51,15 @@ class VersionUpgrade40to41(VersionUpgrade):
parser["general"]["version"] = "4"
parser["metadata"]["setting_version"] = "7"
+ # Limit Maximum Deviation instead of Maximum Resolution. This should have approximately the same effect as before the algorithm change, only more consistent.
+ if "values" in parser and "meshfix_maximum_resolution" in parser["values"]:
+ resolution = parser["values"]["meshfix_maximum_resolution"]
+ if resolution.startswith("="):
+ resolution = resolution[1:]
+ deviation = "=(" + resolution + ") / 2"
+ parser["values"]["meshfix_maximum_deviation"] = deviation
+ del parser["values"]["meshfix_maximum_resolution"]
+
result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
@@ -62,6 +73,11 @@ class VersionUpgrade40to41(VersionUpgrade):
parser["general"]["version"] = "6"
if "metadata" not in parser:
parser["metadata"] = {}
+
+ # Remove changelog plugin
+ if "latest_version_changelog_shown" in parser["general"]:
+ del parser["general"]["latest_version_changelog_shown"]
+
parser["metadata"]["setting_version"] = "7"
result = io.StringIO()
@@ -81,6 +97,13 @@ class VersionUpgrade40to41(VersionUpgrade):
if parser["containers"]["4"] in _renamed_quality_profiles:
parser["containers"]["4"] = _renamed_quality_profiles[parser["containers"]["4"]]
+ # Assign a GlobalStack to a unique group_id. If the GlobalStack has a UM network connection, use the UM network
+ # key as the group_id.
+ if "um_network_key" in parser["metadata"]:
+ parser["metadata"]["group_id"] = parser["metadata"]["um_network_key"]
+ elif "group_id" not in parser["metadata"]:
+ parser["metadata"]["group_id"] = str(uuid.uuid4())
+
result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/__init__.py b/plugins/VersionUpgrade/VersionUpgrade40to41/__init__.py
index 7f39bb9d39..09be805147 100644
--- a/plugins/VersionUpgrade/VersionUpgrade40to41/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade40to41/__init__.py
@@ -14,7 +14,7 @@ def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
- ("preferences", 6000006): ("preferences", 6000007, upgrade.upgradePreferences),
+ ("preferences", 6000006): ("preferences", 6000007, upgrade.upgradePreferences),
("machine_stack", 4000006): ("machine_stack", 4000007, upgrade.upgradeStack),
("extruder_train", 4000006): ("extruder_train", 4000007, upgrade.upgradeStack),
("definition_changes", 4000006): ("definition_changes", 4000007, upgrade.upgradeInstanceContainer),
diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/plugin.json b/plugins/VersionUpgrade/VersionUpgrade40to41/plugin.json
index b1c6d75669..67474508ec 100644
--- a/plugins/VersionUpgrade/VersionUpgrade40to41/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade40to41/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Upgrades configurations from Cura 4.0 to Cura 4.1.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade41to42/VersionUpgrade41to42.py b/plugins/VersionUpgrade/VersionUpgrade41to42/VersionUpgrade41to42.py
new file mode 100644
index 0000000000..305cce16c6
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade41to42/VersionUpgrade41to42.py
@@ -0,0 +1,340 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import configparser
+import io
+import os.path # To get the file ID.
+from typing import Dict, List, Tuple
+
+from UM.VersionUpgrade import VersionUpgrade
+
+_renamed_settings = {
+ "support_minimal_diameter": "support_tower_maximum_supported_diameter"
+} # type: Dict[str, str]
+_removed_settings = ["prime_tower_circular", "max_feedrate_z_override"] # type: List[str]
+_renamed_profiles = {
+ # Include CreawsomeMod profiles here as well for the people who installed that.
+ # Definitions.
+ "creawsome_base": "creality_base",
+ "creawsome_cr10": "creality_cr10",
+ "creawsome_cr10mini": "creality_cr10mini",
+ "creawsome_cr10s": "creality_cr10s",
+ "creawsome_cr10s4": "creality_cr10s4",
+ "creawsome_cr10s5": "creality_cr10s5",
+ "creawsome_cr10spro": "creality_cr10spro",
+ "creawsome_cr20": "creality_cr20",
+ "creawsome_cr20pro": "creality_cr20pro",
+ "creawsome_ender2": "creality_ender2",
+ "creawsome_ender3": "creality_ender3",
+ "creawsome_ender4": "creality_ender4",
+ "creawsome_ender5": "creality_ender5",
+
+ # Extruder definitions.
+ "creawsome_base_extruder_0": "creality_base_extruder_0",
+
+ # Variants.
+ "creawsome_base_0.2": "creality_base_0.2",
+ "creawsome_base_0.3": "creality_base_0.3",
+ "creawsome_base_0.4": "creality_base_0.4",
+ "creawsome_base_0.5": "creality_base_0.5",
+ "creawsome_base_0.6": "creality_base_0.6",
+ "creawsome_base_0.8": "creality_base_0.8",
+ "creawsome_base_1.0": "creality_base_1.0",
+ "creawsome_cr10_0.2": "creality_cr10_0.2",
+ "creawsome_cr10_0.3": "creality_cr10_0.3",
+ "creawsome_cr10_0.4": "creality_cr10_0.4",
+ "creawsome_cr10_0.5": "creality_cr10_0.5",
+ "creawsome_cr10_0.6": "creality_cr10_0.6",
+ "creawsome_cr10_0.8": "creality_cr10_0.8",
+ "creawsome_cr10_1.0": "creality_cr10_1.0",
+ "creawsome_cr10mini_0.2": "creality_cr10mini_0.2",
+ "creawsome_cr10mini_0.3": "creality_cr10mini_0.3",
+ "creawsome_cr10mini_0.4": "creality_cr10mini_0.4",
+ "creawsome_cr10mini_0.5": "creality_cr10mini_0.5",
+ "creawsome_cr10mini_0.6": "creality_cr10mini_0.6",
+ "creawsome_cr10mini_0.8": "creality_cr10mini_0.8",
+ "creawsome_cr10mini_1.0": "creality_cr10mini_1.0",
+ "creawsome_cr10s4_0.2": "creality_cr10s4_0.2",
+ "creawsome_cr10s4_0.3": "creality_cr10s4_0.3",
+ "creawsome_cr10s4_0.4": "creality_cr10s4_0.4",
+ "creawsome_cr10s4_0.5": "creality_cr10s4_0.5",
+ "creawsome_cr10s4_0.6": "creality_cr10s4_0.6",
+ "creawsome_cr10s4_0.8": "creality_cr10s4_0.8",
+ "creawsome_cr10s4_1.0": "creality_cr10s4_1.0",
+ "creawsome_cr10s5_0.2": "creality_cr10s5_0.2",
+ "creawsome_cr10s5_0.3": "creality_cr10s5_0.3",
+ "creawsome_cr10s5_0.4": "creality_cr10s5_0.4",
+ "creawsome_cr10s5_0.5": "creality_cr10s5_0.5",
+ "creawsome_cr10s5_0.6": "creality_cr10s5_0.6",
+ "creawsome_cr10s5_0.8": "creality_cr10s5_0.8",
+ "creawsome_cr10s5_1.0": "creality_cr10s5_1.0",
+ "creawsome_cr10s_0.2": "creality_cr10s_0.2",
+ "creawsome_cr10s_0.3": "creality_cr10s_0.3",
+ "creawsome_cr10s_0.4": "creality_cr10s_0.4",
+ "creawsome_cr10s_0.5": "creality_cr10s_0.5",
+ "creawsome_cr10s_0.6": "creality_cr10s_0.6",
+ "creawsome_cr10s_0.8": "creality_cr10s_0.8",
+ "creawsome_cr10s_1.0": "creality_cr10s_1.0",
+ "creawsome_cr10spro_0.2": "creality_cr10spro_0.2",
+ "creawsome_cr10spro_0.3": "creality_cr10spro_0.3",
+ "creawsome_cr10spro_0.4": "creality_cr10spro_0.4",
+ "creawsome_cr10spro_0.5": "creality_cr10spro_0.5",
+ "creawsome_cr10spro_0.6": "creality_cr10spro_0.6",
+ "creawsome_cr10spro_0.8": "creality_cr10spro_0.8",
+ "creawsome_cr10spro_1.0": "creality_cr10spro_1.0",
+ "creawsome_cr20_0.2": "creality_cr20_0.2",
+ "creawsome_cr20_0.3": "creality_cr20_0.3",
+ "creawsome_cr20_0.4": "creality_cr20_0.4",
+ "creawsome_cr20_0.5": "creality_cr20_0.5",
+ "creawsome_cr20_0.6": "creality_cr20_0.6",
+ "creawsome_cr20_0.8": "creality_cr20_0.8",
+ "creawsome_cr20_1.0": "creality_cr20_1.0",
+ "creawsome_cr20pro_0.2": "creality_cr20pro_0.2",
+ "creawsome_cr20pro_0.3": "creality_cr20pro_0.3",
+ "creawsome_cr20pro_0.4": "creality_cr20pro_0.4",
+ "creawsome_cr20pro_0.5": "creality_cr20pro_0.5",
+ "creawsome_cr20pro_0.6": "creality_cr20pro_0.6",
+ "creawsome_cr20pro_0.8": "creality_cr20pro_0.8",
+ "creawsome_cr20pro_1.0": "creality_cr20pro_1.0",
+ "creawsome_ender2_0.2": "creality_ender2_0.2",
+ "creawsome_ender2_0.3": "creality_ender2_0.3",
+ "creawsome_ender2_0.4": "creality_ender2_0.4",
+ "creawsome_ender2_0.5": "creality_ender2_0.5",
+ "creawsome_ender2_0.6": "creality_ender2_0.6",
+ "creawsome_ender2_0.8": "creality_ender2_0.8",
+ "creawsome_ender2_1.0": "creality_ender2_1.0",
+ "creawsome_ender3_0.2": "creality_ender3_0.2",
+ "creawsome_ender3_0.3": "creality_ender3_0.3",
+ "creawsome_ender3_0.4": "creality_ender3_0.4",
+ "creawsome_ender3_0.5": "creality_ender3_0.5",
+ "creawsome_ender3_0.6": "creality_ender3_0.6",
+ "creawsome_ender3_0.8": "creality_ender3_0.8",
+ "creawsome_ender3_1.0": "creality_ender3_1.0",
+ "creawsome_ender4_0.2": "creality_ender4_0.2",
+ "creawsome_ender4_0.3": "creality_ender4_0.3",
+ "creawsome_ender4_0.4": "creality_ender4_0.4",
+ "creawsome_ender4_0.5": "creality_ender4_0.5",
+ "creawsome_ender4_0.6": "creality_ender4_0.6",
+ "creawsome_ender4_0.8": "creality_ender4_0.8",
+ "creawsome_ender4_1.0": "creality_ender4_1.0",
+ "creawsome_ender5_0.2": "creality_ender5_0.2",
+ "creawsome_ender5_0.3": "creality_ender5_0.3",
+ "creawsome_ender5_0.4": "creality_ender5_0.4",
+ "creawsome_ender5_0.5": "creality_ender5_0.5",
+ "creawsome_ender5_0.6": "creality_ender5_0.6",
+ "creawsome_ender5_0.8": "creality_ender5_0.8",
+ "creawsome_ender5_1.0": "creality_ender5_1.0",
+
+ # Upgrade for people who had the original Creality profiles from 4.1 and earlier.
+ "creality_cr10_extruder_0": "creality_base_extruder_0",
+ "creality_cr10s4_extruder_0": "creality_base_extruder_0",
+ "creality_cr10s5_extruder_0": "creality_base_extruder_0",
+ "creality_ender3_extruder_0": "creality_base_extruder_0"
+}
+
+# For legacy Creality printers, select the correct quality profile depending on the material.
+_creality_quality_per_material = {
+ # Since legacy Creality printers didn't have different variants, we always pick the 0.4mm variant.
+ "generic_abs_175": {
+ "high": "base_0.4_ABS_super",
+ "normal": "base_0.4_ABS_super",
+ "fast": "base_0.4_ABS_super",
+ "draft": "base_0.4_ABS_standard",
+ "extra_fast": "base_0.4_ABS_low",
+ "coarse": "base_0.4_ABS_low",
+ "extra_coarse": "base_0.4_ABS_low"
+ },
+ "generic_petg_175": {
+ "high": "base_0.4_PETG_super",
+ "normal": "base_0.4_PETG_super",
+ "fast": "base_0.4_PETG_super",
+ "draft": "base_0.4_PETG_standard",
+ "extra_fast": "base_0.4_PETG_low",
+ "coarse": "base_0.4_PETG_low",
+ "extra_coarse": "base_0.4_PETG_low"
+ },
+ "generic_pla_175": {
+ "high": "base_0.4_PLA_super",
+ "normal": "base_0.4_PLA_super",
+ "fast": "base_0.4_PLA_super",
+ "draft": "base_0.4_PLA_standard",
+ "extra_fast": "base_0.4_PLA_low",
+ "coarse": "base_0.4_PLA_low",
+ "extra_coarse": "base_0.4_PLA_low"
+ },
+ "generic_tpu_175": {
+ "high": "base_0.4_TPU_super",
+ "normal": "base_0.4_TPU_super",
+ "fast": "base_0.4_TPU_super",
+ "draft": "base_0.4_TPU_standard",
+ "extra_fast": "base_0.4_TPU_standard",
+ "coarse": "base_0.4_TPU_standard",
+ "extra_coarse": "base_0.4_TPU_standard"
+ },
+ "empty_material": { # For the global stack.
+ "high": "base_global_super",
+ "normal": "base_global_super",
+ "fast": "base_global_super",
+ "draft": "base_global_standard",
+ "extra_fast": "base_global_low",
+ "coarse": "base_global_low",
+ "extra_coarse": "base_global_low"
+ }
+}
+
+# Default variant to select for legacy Creality printers, now that we have variants.
+_default_variants = {
+ "creality_cr10_extruder_0": "creality_cr10_0.4",
+ "creality_cr10s4_extruder_0": "creality_cr10s4_0.4",
+ "creality_cr10s5_extruder_0": "creality_cr10s5_0.4",
+ "creality_ender3_extruder_0": "creality_ender3_0.4"
+}
+
+# Whether the quality changes profile belongs to one of the upgraded printers can only be recognised by how they start.
+# If they are, they must use the creality base definition so that they still belong to those printers.
+_quality_changes_to_creality_base = {
+ "creality_cr10_extruder_0",
+ "creality_cr10s4_extruder_0",
+ "creality_cr10s5_extruder_0",
+ "creality_ender3_extruder_0",
+ "creality_cr10",
+ "creality_cr10s",
+ "creality_cr10s4",
+ "creality_cr10s5",
+ "creality_ender3",
+}
+_creality_limited_quality_type = {
+ "high": "super",
+ "normal": "super",
+ "fast": "super",
+ "draft": "draft",
+ "extra_fast": "draft",
+ "coarse": "draft",
+ "extra_coarse": "draft"
+}
+
+## Upgrades configurations from the state they were in at version 4.1 to the
+# state they should be in at version 4.2.
+class VersionUpgrade41to42(VersionUpgrade):
+ ## Gets the version number from a CFG file in Uranium's 4.1 format.
+ #
+ # Since the format may change, this is implemented for the 4.1 format only
+ # and needs to be included in the version upgrade system rather than
+ # globally in Uranium.
+ #
+ # \param serialised The serialised form of a CFG file.
+ # \return The version number stored in the CFG file.
+ # \raises ValueError The format of the version number in the file is
+ # incorrect.
+ # \raises KeyError The format of the file is incorrect.
+ def getCfgVersion(self, serialised: str) -> int:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialised)
+ format_version = int(parser.get("general", "version")) # Explicitly give an exception when this fails. That means that the file format is not recognised.
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
+ return format_version * 1000000 + setting_version
+
+ ## Upgrades instance containers to have the new version
+ # number.
+ #
+ # This renames the renamed settings in the containers.
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "8"
+
+ # Certain instance containers (such as definition changes) reference to a certain definition container
+ # Since a number of those changed name, we also need to update those.
+ old_definition = parser["general"]["definition"]
+ if old_definition in _renamed_profiles:
+ parser["general"]["definition"] = _renamed_profiles[old_definition]
+
+ # Rename settings.
+ if "values" in parser:
+ for old_name, new_name in _renamed_settings.items():
+ if old_name in parser["values"]:
+ parser["values"][new_name] = parser["values"][old_name]
+ del parser["values"][old_name]
+ # Remove settings.
+ for key in _removed_settings:
+ if key in parser["values"]:
+ del parser["values"][key]
+
+ # For quality-changes profiles made for Creality printers, change the definition to the creality_base and make sure that the quality is something we have a profile for.
+ if parser["metadata"].get("type", "") == "quality_changes":
+ for possible_printer in _quality_changes_to_creality_base:
+ if os.path.basename(filename).startswith(possible_printer + "_"):
+ parser["general"]["definition"] = "creality_base"
+ parser["metadata"]["quality_type"] = _creality_limited_quality_type.get(parser["metadata"]["quality_type"], "draft")
+ break
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades Preferences to have the new version number.
+ #
+ # This renames the renamed settings in the list of visible settings.
+ def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "8"
+
+ # Renamed settings.
+ if "visible_settings" in parser["general"]:
+ visible_settings = parser["general"]["visible_settings"]
+ visible_setting_set = set(visible_settings.split(";"))
+ for old_name, new_name in _renamed_settings.items():
+ if old_name in visible_setting_set:
+ visible_setting_set.remove(old_name)
+ visible_setting_set.add(new_name)
+ for removed_key in _removed_settings:
+ if removed_key in visible_setting_set:
+ visible_setting_set.remove(removed_key)
+ parser["general"]["visible_settings"] = ";".join(visible_setting_set)
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades stacks to have the new version number.
+ def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "8"
+
+ # Change renamed profiles.
+ if "containers" in parser:
+ # For legacy Creality printers, change the variant to 0.4.
+ definition_id = parser["containers"]["6"]
+ if parser["metadata"].get("type", "machine") == "extruder_train":
+ if parser["containers"]["4"] == "empty_variant": # Necessary for people entering from CreawsomeMod who already had a variant.
+ if definition_id in _default_variants:
+ parser["containers"]["4"] = _default_variants[definition_id]
+ if definition_id == "creality_cr10_extruder_0": # We can't disambiguate between Creality CR-10 and Creality-CR10S since they share the same extruder definition. Have to go by the name.
+ if "cr-10s" in parser["metadata"].get("machine", "Creality CR-10").lower(): # Not perfect, since the user can change this name :(
+ parser["containers"]["4"] = "creality_cr10s_0.4"
+
+ # Also change the quality to go along with it.
+ material_id = parser["containers"]["3"]
+ old_quality_id = parser["containers"]["2"]
+ if material_id in _creality_quality_per_material and old_quality_id in _creality_quality_per_material[material_id]:
+ if definition_id == "creality_cr10_extruder_0": # We can't disambiguate between Creality CR-10 and Creality-CR10S since they share the same extruder definition. Have to go by the name.
+ if "cr-10s" in parser["metadata"].get("machine", "Creality CR-10").lower(): # Not perfect, since the user can change this name :(
+ parser["containers"]["2"] = _creality_quality_per_material[material_id][old_quality_id]
+
+ stack_copy = {} # type: Dict[str, str] # Make a copy so that we don't modify the dict we're iterating over.
+ stack_copy.update(parser["containers"])
+ for position, profile_id in stack_copy.items():
+ if profile_id in _renamed_profiles:
+ parser["containers"][position] = _renamed_profiles[profile_id]
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
diff --git a/plugins/VersionUpgrade/VersionUpgrade41to42/__init__.py b/plugins/VersionUpgrade/VersionUpgrade41to42/__init__.py
new file mode 100644
index 0000000000..8fe718ca83
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade41to42/__init__.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Any, Dict, TYPE_CHECKING
+
+from . import VersionUpgrade41to42
+
+if TYPE_CHECKING:
+ from UM.Application import Application
+
+upgrade = VersionUpgrade41to42.VersionUpgrade41to42()
+
+def getMetaData() -> Dict[str, Any]:
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("preferences", 6000007): ("preferences", 6000008, upgrade.upgradePreferences),
+ ("machine_stack", 4000007): ("machine_stack", 4000008, upgrade.upgradeStack),
+ ("extruder_train", 4000007): ("extruder_train", 4000008, upgrade.upgradeStack),
+ ("definition_changes", 4000007): ("definition_changes", 4000008, upgrade.upgradeInstanceContainer),
+ ("quality_changes", 4000007): ("quality_changes", 4000008, upgrade.upgradeInstanceContainer),
+ ("quality", 4000007): ("quality", 4000008, upgrade.upgradeInstanceContainer),
+ ("user", 4000007): ("user", 4000008, upgrade.upgradeInstanceContainer),
+ },
+ "sources": {
+ "preferences": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"."}
+ },
+ "machine_stack": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./machine_instances"}
+ },
+ "extruder_train": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./extruders"}
+ },
+ "definition_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./definition_changes"}
+ },
+ "quality_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality_changes"}
+ },
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
+ "user": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./user"}
+ }
+ }
+ }
+
+
+def register(app: "Application") -> Dict[str, Any]:
+ return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade41to42/plugin.json b/plugins/VersionUpgrade/VersionUpgrade41to42/plugin.json
new file mode 100644
index 0000000000..506000aae9
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade41to42/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Version Upgrade 4.1 to 4.2",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Upgrades configurations from Cura 4.1 to Cura 4.2.",
+ "api": "7.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade42to43/VersionUpgrade42to43.py b/plugins/VersionUpgrade/VersionUpgrade42to43/VersionUpgrade42to43.py
new file mode 100644
index 0000000000..d6489f6d8b
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade42to43/VersionUpgrade42to43.py
@@ -0,0 +1,160 @@
+import configparser
+import io
+from typing import Dict, Tuple, List
+
+from UM.VersionUpgrade import VersionUpgrade
+
+_renamed_profiles = {"generic_pla_0.4_coarse": "jbo_generic_pla_0.4_coarse",
+ "generic_pla_0.4_fine": "jbo_generic_pla_fine",
+ "generic_pla_0.4_medium": "jbo_generic_pla_medium",
+ "generic_pla_0.4_ultrafine": "jbo_generic_pla_ultrafine",
+
+ "generic_petg_0.4_coarse": "jbo_generic_petg_0.4_coarse",
+ "generic_petg_0.4_fine": "jbo_generic_petg_fine",
+ "generic_petg_0.4_medium": "jbo_generic_petg_medium",
+ }
+
+# - The variant "imade3d jellybox 0.4 mm 2-fans" for machine definition "imade3d_jellybox"
+# is now "0.4 mm" for machine definition "imade3d jellybox_2".
+# - Materials "imade3d_petg_green" and "imade3d_petg_pink" are now "imade3d_petg_175".
+# - Materials "imade3d_pla_green" and "imade3d_pla_pink" are now "imade3d_petg_175".
+#
+# Note: Theoretically, the old material profiles with "_2-fans" at the end should be updated to:
+# - machine definition: imade3d_jellybox_2
+# - variant: 0.4 mm (for jellybox 2)
+# - material: (as an example) imade3d_petg_175_imade3d_jellybox_2_0.4_mm
+#
+# But this involves changing the definition of the global stack and the extruder stacks, which can cause more trouble
+# than what we can fix. So, here, we update all material variants, regardless of having "_2-fans" at the end or not, to
+# jellybox_0.4_mm.
+#
+_renamed_material_profiles = { # PETG
+ "imade3d_petg_green": "imade3d_petg_175",
+ "imade3d_petg_green_imade3d_jellybox": "imade3d_petg_175_imade3d_jellybox",
+ "imade3d_petg_green_imade3d_jellybox_0.4_mm": "imade3d_petg_175_imade3d_jellybox_0.4_mm",
+ "imade3d_petg_green_imade3d_jellybox_0.4_mm_2-fans": "imade3d_petg_175_imade3d_jellybox_0.4_mm",
+ "imade3d_petg_pink": "imade3d_petg_175",
+ "imade3d_petg_pink_imade3d_jellybox": "imade3d_petg_175_imade3d_jellybox",
+ "imade3d_petg_pink_imade3d_jellybox_0.4_mm": "imade3d_petg_175_imade3d_jellybox_0.4_mm",
+ "imade3d_petg_pink_imade3d_jellybox_0.4_mm_2-fans": "imade3d_petg_175_imade3d_jellybox_0.4_mm",
+ # PLA
+ "imade3d_pla_green": "imade3d_pla_175",
+ "imade3d_pla_green_imade3d_jellybox": "imade3d_pla_175_imade3d_jellybox",
+ "imade3d_pla_green_imade3d_jellybox_0.4_mm": "imade3d_pla_175_imade3d_jellybox_0.4_mm",
+ "imade3d_pla_green_imade3d_jellybox_0.4_mm_2-fans": "imade3d_pla_175_imade3d_jellybox_0.4_mm",
+ "imade3d_pla_pink": "imade3d_pla_175",
+ "imade3d_pla_pink_imade3d_jellybox": "imade3d_pla_175_imade3d_jellybox",
+ "imade3d_pla_pink_imade3d_jellybox_0.4_mm": "imade3d_pla_175_imade3d_jellybox_0.4_mm",
+ "imade3d_pla_pink_imade3d_jellybox_0.4_mm_2-fans": "imade3d_pla_175_imade3d_jellybox_0.4_mm",
+ }
+
+_removed_settings = {
+ "start_layers_at_same_position"
+}
+
+_renamed_settings = {
+ "support_infill_angle": "support_infill_angles"
+} # type: Dict[str, str]
+
+## Upgrades configurations from the state they were in at version 4.2 to the
+# state they should be in at version 4.3.
+class VersionUpgrade42to43(VersionUpgrade):
+ ## Gets the version number from a CFG file in Uranium's 4.2 format.
+ #
+ # Since the format may change, this is implemented for the 4.2 format only
+ # and needs to be included in the version upgrade system rather than
+ # globally in Uranium.
+ #
+ # \param serialised The serialised form of a CFG file.
+ # \return The version number stored in the CFG file.
+ # \raises ValueError The format of the version number in the file is
+ # incorrect.
+ # \raises KeyError The format of the file is incorrect.
+ def getCfgVersion(self, serialised: str) -> int:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialised)
+ format_version = int(parser.get("general", "version")) # Explicitly give an exception when this fails. That means that the file format is not recognised.
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
+ return format_version * 1000000 + setting_version
+
+ def upgradePreferences(self, serialized: str, filename: str):
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ if "camera_perspective_mode" in parser["general"] and parser["general"]["camera_perspective_mode"] == "orthogonal":
+ parser["general"]["camera_perspective_mode"] = "orthographic"
+
+ # Fix renamed settings for visibility
+ if "visible_settings" in parser["general"]:
+ all_setting_keys = parser["general"]["visible_settings"].strip().split(";")
+ if all_setting_keys:
+ for idx, key in enumerate(all_setting_keys):
+ if key in _renamed_settings:
+ all_setting_keys[idx] = _renamed_settings[key]
+ parser["general"]["visible_settings"] = ";".join(all_setting_keys)
+
+ parser["metadata"]["setting_version"] = "9"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades instance containers to have the new version
+ # number.
+ #
+ # This renames the renamed settings in the containers.
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "9"
+
+ if "values" in parser:
+ for old_name, new_name in _renamed_settings.items():
+ if old_name in parser["values"]:
+ parser["values"][new_name] = parser["values"][old_name]
+ del parser["values"][old_name]
+ for key in _removed_settings:
+ if key in parser["values"]:
+ del parser["values"][key]
+
+ if "support_infill_angles" in parser["values"]:
+ old_value = float(parser["values"]["support_infill_angles"])
+ new_value = [int(round(old_value))]
+ parser["values"]["support_infill_angles"] = str(new_value)
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades stacks to have the new version number.
+ def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "9"
+ # Handle changes for the imade3d jellybox. The machine was split up into parts (eg; a 2 fan version and a single
+ # fan version. Perviously it used variants for this. The only upgrade we can do here is strip that variant.
+ # This is because we only upgrade per stack (and to fully do these changes, we'd need to switch out something
+ # in the global container based on changes made to the extruder stack)
+ if parser["containers"]["6"] == "imade3d_jellybox_extruder_0":
+ quality_id = parser["containers"]["2"]
+ if quality_id.endswith("_2-fans"):
+ parser["containers"]["2"] = quality_id.replace("_2-fans", "")
+
+ if parser["containers"]["2"] in _renamed_profiles:
+ parser["containers"]["2"] = _renamed_profiles[parser["containers"]["2"]]
+
+ material_id = parser["containers"]["3"]
+ if material_id in _renamed_material_profiles:
+ parser["containers"]["3"] = _renamed_material_profiles[material_id]
+ variant_id = parser["containers"]["4"]
+
+ if variant_id.endswith("_2-fans"):
+ parser["containers"]["4"] = variant_id.replace("_2-fans", "")
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
diff --git a/plugins/VersionUpgrade/VersionUpgrade42to43/__init__.py b/plugins/VersionUpgrade/VersionUpgrade42to43/__init__.py
new file mode 100644
index 0000000000..7400bbb989
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade42to43/__init__.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Any, Dict, TYPE_CHECKING
+
+from . import VersionUpgrade42to43
+
+if TYPE_CHECKING:
+ from UM.Application import Application
+
+upgrade = VersionUpgrade42to43.VersionUpgrade42to43()
+
+def getMetaData() -> Dict[str, Any]:
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("preferences", 6000008): ("preferences", 6000009, upgrade.upgradePreferences),
+ ("machine_stack", 4000008): ("machine_stack", 4000009, upgrade.upgradeStack),
+ ("extruder_train", 4000008): ("extruder_train", 4000009, upgrade.upgradeStack),
+ ("definition_changes", 4000008): ("definition_changes", 4000009, upgrade.upgradeInstanceContainer),
+ ("quality_changes", 4000008): ("quality_changes", 4000009, upgrade.upgradeInstanceContainer),
+ ("quality", 4000008): ("quality", 4000009, upgrade.upgradeInstanceContainer),
+ ("user", 4000008): ("user", 4000009, upgrade.upgradeInstanceContainer),
+ },
+ "sources": {
+ "preferences": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"."}
+ },
+ "machine_stack": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./machine_instances"}
+ },
+ "extruder_train": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./extruders"}
+ },
+ "definition_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./definition_changes"}
+ },
+ "quality_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality_changes"}
+ },
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
+ "user": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./user"}
+ }
+ }
+ }
+
+
+def register(app: "Application") -> Dict[str, Any]:
+ return { "version_upgrade": upgrade }
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade42to43/plugin.json b/plugins/VersionUpgrade/VersionUpgrade42to43/plugin.json
new file mode 100644
index 0000000000..8a5e838668
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade42to43/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Version Upgrade 4.2 to 4.3",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Upgrades configurations from Cura 4.2 to Cura 4.3.",
+ "api": "7.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py b/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py
new file mode 100644
index 0000000000..8b69852cb2
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade43to44/VersionUpgrade43to44.py
@@ -0,0 +1,122 @@
+import configparser
+from typing import Tuple, List
+import io
+from UM.VersionUpgrade import VersionUpgrade
+from UM.Util import parseBool # To parse whether the Alternate Skin Rotations function is activated.
+
+_renamed_container_id_map = {
+ "ultimaker2_0.25": "ultimaker2_olsson_0.25",
+ "ultimaker2_0.4": "ultimaker2_olsson_0.4",
+ "ultimaker2_0.6": "ultimaker2_olsson_0.6",
+ "ultimaker2_0.8": "ultimaker2_olsson_0.8",
+ "ultimaker2_extended_0.25": "ultimaker2_extended_olsson_0.25",
+ "ultimaker2_extended_0.4": "ultimaker2_extended_olsson_0.4",
+ "ultimaker2_extended_0.6": "ultimaker2_extended_olsson_0.6",
+ "ultimaker2_extended_0.8": "ultimaker2_extended_olsson_0.8",
+ # HMS434 "extra coarse", "super coarse", and "ultra coarse" are removed.
+ "hms434_global_Extra_Coarse_Quality": "hms434_global_Normal_Quality",
+ "hms434_global_Super_Coarse_Quality": "hms434_global_Normal_Quality",
+ "hms434_global_Ultra_Coarse_Quality": "hms434_global_Normal_Quality",
+ # HMS434 "0.25", "0.6", "1.2", and "1.5" nozzles are removed.
+ "hms434_0.25tpnozzle": "hms434_0.4tpnozzle",
+ "hms434_0.6tpnozzle": "hms434_0.4tpnozzle",
+ "hms434_1.2tpnozzle": "hms434_0.4tpnozzle",
+ "hms434_1.5tpnozzle": "hms434_0.4tpnozzle",
+}
+
+
+class VersionUpgrade43to44(VersionUpgrade):
+ def getCfgVersion(self, serialised: str) -> int:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialised)
+ format_version = int(parser.get("general", "version")) # Explicitly give an exception when this fails. That means that the file format is not recognised.
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
+ return format_version * 1000000 + setting_version
+
+ ## Upgrades Preferences to have the new version number.
+ #
+ # This renames the renamed settings in the list of visible settings.
+ def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "10"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades instance containers to have the new version
+ # number.
+ #
+ # This renames the renamed settings in the containers.
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "10"
+
+ # Intent profiles were added, so the quality changes should match with no intent (so "default")
+ if parser["metadata"].get("type", "") == "quality_changes":
+ parser["metadata"]["intent_category"] = "default"
+
+ if "values" in parser:
+ # Alternate skin rotation should be translated to top/bottom line directions.
+ if "skin_alternate_rotation" in parser["values"] and parseBool(parser["values"]["skin_alternate_rotation"]):
+ parser["values"]["skin_angles"] = "[45, 135, 0, 90]"
+ # Unit of adaptive layers topography size changed.
+ if "adaptive_layer_height_threshold" in parser["values"]:
+ val = parser["values"]["adaptive_layer_height_threshold"]
+ if val.startswith("="):
+ val = val[1:]
+ val = "=({val}) / 1000".format(val = val) # Convert microns to millimetres. Works even if the profile contained a formula.
+ parser["values"]["adaptive_layer_height_threshold"] = val
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades stacks to have the new version number.
+ def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ if "metadata" not in parser:
+ parser["metadata"] = {}
+ parser["metadata"]["setting_version"] = "10"
+
+ if "containers" in parser:
+ # With the ContainerTree refactor, UM2 with Olsson block got moved to a separate definition.
+ if "6" in parser["containers"]:
+ if parser["containers"]["6"] == "ultimaker2":
+ if "metadata" in parser and "has_variants" in parser["metadata"] and parser["metadata"]["has_variants"] == "True": # This is an Olsson block upgraded UM2!
+ parser["containers"]["6"] = "ultimaker2_olsson"
+ del parser["metadata"]["has_variants"]
+ elif parser["containers"]["6"] == "ultimaker2_extended":
+ if "metadata" in parser and "has_variants" in parser["metadata"] and parser["metadata"]["has_variants"] == "True": # This is an Olsson block upgraded UM2E!
+ parser["containers"]["6"] = "ultimaker2_extended_olsson"
+ del parser["metadata"]["has_variants"]
+
+ # We should only have 6 levels when we start.
+ if "7" in parser["containers"]:
+ return ([], [])
+
+ # We added the intent container in Cura 4.4. This means that all other containers move one step down.
+ parser["containers"]["7"] = parser["containers"]["6"]
+ parser["containers"]["6"] = parser["containers"]["5"]
+ parser["containers"]["5"] = parser["containers"]["4"]
+ parser["containers"]["4"] = parser["containers"]["3"]
+ parser["containers"]["3"] = parser["containers"]["2"]
+ parser["containers"]["2"] = "empty_intent"
+
+ # Update renamed containers
+ for key, value in parser["containers"].items():
+ if value in _renamed_container_id_map:
+ parser["containers"][key] = _renamed_container_id_map[value]
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
diff --git a/plugins/VersionUpgrade/VersionUpgrade43to44/__init__.py b/plugins/VersionUpgrade/VersionUpgrade43to44/__init__.py
new file mode 100644
index 0000000000..506ec6c03d
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade43to44/__init__.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Any, Dict, TYPE_CHECKING
+
+from . import VersionUpgrade43to44
+
+
+if TYPE_CHECKING:
+ from UM.Application import Application
+
+upgrade = VersionUpgrade43to44.VersionUpgrade43to44()
+
+
+def getMetaData() -> Dict[str, Any]:
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("preferences", 6000009): ("preferences", 6000010, upgrade.upgradePreferences),
+ ("machine_stack", 4000009): ("machine_stack", 4000010, upgrade.upgradeStack),
+ ("extruder_train", 4000009): ("extruder_train", 4000010, upgrade.upgradeStack),
+ ("definition_changes", 4000009): ("definition_changes", 4000010, upgrade.upgradeInstanceContainer),
+ ("quality_changes", 4000009): ("quality_changes", 4000010, upgrade.upgradeInstanceContainer),
+ ("quality", 4000009): ("quality", 4000010, upgrade.upgradeInstanceContainer),
+ ("user", 4000009): ("user", 4000010, upgrade.upgradeInstanceContainer),
+ },
+ "sources": {
+ "preferences": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"."}
+ },
+ "machine_stack": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./machine_instances"}
+ },
+ "extruder_train": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./extruders"}
+ },
+ "definition_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./definition_changes"}
+ },
+ "quality_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality_changes"}
+ },
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
+ "user": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./user"}
+ }
+ }
+ }
+
+
+def register(app: "Application") -> Dict[str, Any]:
+ return {"version_upgrade": upgrade}
diff --git a/plugins/VersionUpgrade/VersionUpgrade43to44/plugin.json b/plugins/VersionUpgrade/VersionUpgrade43to44/plugin.json
new file mode 100644
index 0000000000..37575396e3
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade43to44/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Version Upgrade 4.3 to 4.4",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Upgrades configurations from Cura 4.3 to Cura 4.4.",
+ "api": "7.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade43to44/tests/TestVersionUpgrade43To44.py b/plugins/VersionUpgrade/VersionUpgrade43to44/tests/TestVersionUpgrade43To44.py
new file mode 100644
index 0000000000..dc770c2c6f
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade43to44/tests/TestVersionUpgrade43To44.py
@@ -0,0 +1,36 @@
+import configparser
+
+import VersionUpgrade43to44
+
+before_update = """[general]
+version = 4
+name = Ultimaker 3
+id = Ultimaker 3
+
+[metadata]
+type = machine
+
+[containers]
+0 = user_profile
+1 = quality_changes
+2 = quality
+3 = material
+4 = variant
+5 = definition_changes
+6 = definition
+"""
+
+
+def test_upgrade():
+ upgrader = VersionUpgrade43to44.VersionUpgrade43to44()
+ file_name, new_data = upgrader.upgradeStack(before_update, "whatever")
+ parser = configparser.ConfigParser(interpolation=None)
+ parser.read_string(new_data[0])
+ assert parser["containers"]["0"] == "user_profile"
+ assert parser["containers"]["1"] == "quality_changes"
+ assert parser["containers"]["2"] == "empty_intent"
+ assert parser["containers"]["3"] == "quality"
+ assert parser["containers"]["4"] == "material"
+ assert parser["containers"]["5"] == "variant"
+ assert parser["containers"]["6"] == "definition_changes"
+ assert parser["containers"]["7"] == "definition"
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade44to45/VersionUpgrade44to45.py b/plugins/VersionUpgrade/VersionUpgrade44to45/VersionUpgrade44to45.py
new file mode 100644
index 0000000000..1d278764f0
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade44to45/VersionUpgrade44to45.py
@@ -0,0 +1,69 @@
+import configparser
+from typing import Tuple, List
+import io
+from UM.VersionUpgrade import VersionUpgrade
+
+# Merged preferences: machine_head_polygon and machine_head_with_fans_polygon -> machine_head_with_fans_polygon
+# When both are present, machine_head_polygon will be removed
+# When only one of the two is present, it's value will be used
+
+
+class VersionUpgrade44to45(VersionUpgrade):
+ def getCfgVersion(self, serialised: str) -> int:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialised)
+ format_version = int(parser.get("general", "version")) # Explicitly give an exception when this fails. That means that the file format is not recognised.
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
+ return format_version * 1000000 + setting_version
+
+ ## Upgrades Preferences to have the new version number.
+ #
+ # This renames the renamed settings in the list of visible settings.
+ def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "11"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades instance containers to have the new version
+ # number.
+ #
+ # This renames the renamed settings in the containers.
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None, comment_prefixes=())
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "11"
+
+ if "values" in parser:
+ # merge machine_head_with_fans_polygon (preferred) and machine_head_polygon
+ if "machine_head_with_fans_polygon" in parser["values"]:
+ if "machine_head_polygon" in parser["values"]:
+ del parser["values"]["machine_head_polygon"]
+ elif "machine_head_polygon" in parser["values"]:
+ parser["values"]["machine_head_with_fans_polygon"] = parser["values"]["machine_head_polygon"]
+ del parser["values"]["machine_head_polygon"]
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades stacks to have the new version number.
+ def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ if "metadata" not in parser:
+ parser["metadata"] = {}
+ parser["metadata"]["setting_version"] = "11"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
diff --git a/plugins/VersionUpgrade/VersionUpgrade44to45/__init__.py b/plugins/VersionUpgrade/VersionUpgrade44to45/__init__.py
new file mode 100644
index 0000000000..06a9d66c50
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade44to45/__init__.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Any, Dict, TYPE_CHECKING
+
+from . import VersionUpgrade44to45
+
+
+if TYPE_CHECKING:
+ from UM.Application import Application
+
+upgrade = VersionUpgrade44to45.VersionUpgrade44to45()
+
+
+def getMetaData() -> Dict[str, Any]:
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("preferences", 6000010): ("preferences", 6000011, upgrade.upgradePreferences),
+ ("machine_stack", 4000010): ("machine_stack", 4000011, upgrade.upgradeStack),
+ ("extruder_train", 4000010): ("extruder_train", 4000011, upgrade.upgradeStack),
+ ("definition_changes", 4000010): ("definition_changes", 4000011, upgrade.upgradeInstanceContainer),
+ ("quality_changes", 4000010): ("quality_changes", 4000011, upgrade.upgradeInstanceContainer),
+ ("quality", 4000010): ("quality", 4000011, upgrade.upgradeInstanceContainer),
+ ("user", 4000010): ("user", 4000011, upgrade.upgradeInstanceContainer),
+ },
+ "sources": {
+ "preferences": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"."}
+ },
+ "machine_stack": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./machine_instances"}
+ },
+ "extruder_train": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./extruders"}
+ },
+ "definition_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./definition_changes"}
+ },
+ "quality_changes": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality_changes"}
+ },
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
+ "user": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./user"}
+ }
+ }
+ }
+
+
+def register(app: "Application") -> Dict[str, Any]:
+ return {"version_upgrade": upgrade}
diff --git a/plugins/VersionUpgrade/VersionUpgrade44to45/plugin.json b/plugins/VersionUpgrade/VersionUpgrade44to45/plugin.json
new file mode 100644
index 0000000000..f7b6157118
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade44to45/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Version Upgrade 4.4 to 4.5",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Upgrades configurations from Cura 4.4 to Cura 4.5.",
+ "api": "7.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade44to45/tests/TestVersionUpgrade44To45.py b/plugins/VersionUpgrade/VersionUpgrade44to45/tests/TestVersionUpgrade44To45.py
new file mode 100644
index 0000000000..0c1bb55985
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade44to45/tests/TestVersionUpgrade44To45.py
@@ -0,0 +1,42 @@
+import configparser
+
+import VersionUpgrade44to45
+import pytest
+
+before_update = """[general]
+version = 4
+name = Creality CR-10S_settings
+definition = creality_cr10s
+
+[metadata]
+type = definition_changes
+setting_version = 11
+
+[values]
+%s
+"""
+before_after_list = [
+ ("machine_head_with_fans_polygon = [[-99, 99], [-99, -44], [45, 99], [45, -44]]", "[[-99, 99], [-99, -44], [45, 99], [45, -44]]"),
+ ("", None),
+ ("machine_head_polygon = [[-98, 99], [-99, -44], [45, 99], [45, -44]]", "[[-98, 99], [-99, -44], [45, 99], [45, -44]]"),
+ ("machine_head_polygon = [[-87, 99], [-99, -44], [45, 99], [45, -44]]\nmachine_head_with_fans_polygon = [[-99, 99], [-99, -44], [45, 99], [45, -44]]", "[[-99, 99], [-99, -44], [45, 99], [45, -44]]"),
+ ]
+
+
+class TestVersionUpgrade44to45:
+
+ @pytest.mark.parametrize("after_string, after_value", before_after_list)
+ def test_upgrade(self, after_string, after_value):
+ upgrader = VersionUpgrade44to45.VersionUpgrade44to45()
+
+
+ file_name, new_data = upgrader.upgradeInstanceContainer(before_update % after_string, "whatever")
+ parser = configparser.ConfigParser(interpolation=None)
+ parser.read_string(new_data[0])
+
+ if after_value is None:
+ assert "machine_head_with_fans_polygon" not in parser["values"]
+ else:
+ assert parser["values"]["machine_head_with_fans_polygon"] == after_value
+
+ assert "machine_head_polygon" not in parser["values"]
\ No newline at end of file
diff --git a/plugins/X3DReader/plugin.json b/plugins/X3DReader/plugin.json
index 1fc14104ed..17bb3a96d1 100644
--- a/plugins/X3DReader/plugin.json
+++ b/plugins/X3DReader/plugin.json
@@ -3,6 +3,6 @@
"author": "Seva Alekseyev",
"version": "1.0.1",
"description": "Provides support for reading X3D files.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/XRayView/XRayView.py b/plugins/XRayView/XRayView.py
index 86533fe51c..88a5a441b8 100644
--- a/plugins/XRayView/XRayView.py
+++ b/plugins/XRayView/XRayView.py
@@ -10,21 +10,21 @@ from UM.Math.Color import Color
from UM.PluginRegistry import PluginRegistry
from UM.Platform import Platform
from UM.Event import Event
-from UM.View.View import View
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
from cura.CuraApplication import CuraApplication
+from cura.CuraView import CuraView
from cura.Scene.ConvexHullNode import ConvexHullNode
from . import XRayPass
## View used to display a see-through version of objects with errors highlighted.
-class XRayView(View):
+class XRayView(CuraView):
def __init__(self):
- super().__init__()
+ super().__init__(parent = None, use_empty_menu_placeholder = True)
self._xray_shader = None
self._xray_pass = None
diff --git a/plugins/XRayView/plugin.json b/plugins/XRayView/plugin.json
index 71cc165b6c..ff220ed97c 100644
--- a/plugins/XRayView/plugin.json
+++ b/plugins/XRayView/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides the X-Ray view.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/XRayView/xray.shader b/plugins/XRayView/xray.shader
index 41b00154ea..45cb16c44c 100644
--- a/plugins/XRayView/xray.shader
+++ b/plugins/XRayView/xray.shader
@@ -1,12 +1,14 @@
[shaders]
vertex =
- uniform highp mat4 u_modelViewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
attribute highp vec4 a_vertex;
void main()
{
- gl_Position = u_modelViewProjectionMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
}
fragment =
@@ -19,13 +21,15 @@ fragment =
vertex41core =
#version 410
- uniform highp mat4 u_modelViewProjectionMatrix;
+ uniform highp mat4 u_modelMatrix;
+ uniform highp mat4 u_viewMatrix;
+ uniform highp mat4 u_projectionMatrix;
in highp vec4 a_vertex;
void main()
{
- gl_Position = u_modelViewProjectionMatrix * a_vertex;
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
}
fragment41core =
@@ -43,7 +47,9 @@ fragment41core =
u_color = [0.02, 0.02, 0.02, 1.0]
[bindings]
-u_modelViewProjectionMatrix = model_view_projection_matrix
+u_modelMatrix = model_matrix
+u_viewMatrix = view_matrix
+u_projectionMatrix = projection_matrix
[attributes]
a_vertex = vertex
diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
index 27c401fcd4..52b204affc 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
@@ -6,7 +6,7 @@ import io
import json #To parse the product-to-id mapping file.
import os.path #To find the product-to-id mapping.
import sys
-from typing import Any, Dict, List, Optional, Tuple, cast, Set
+from typing import Any, Dict, List, Optional, Tuple, cast, Set, Union
import xml.etree.ElementTree as ET
from UM.Resources import Resources
@@ -17,9 +17,13 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
from cura.CuraApplication import CuraApplication
+from cura.Machines.ContainerTree import ContainerTree
from cura.Machines.VariantType import VariantType
-from .XmlMaterialValidator import XmlMaterialValidator
+try:
+ from .XmlMaterialValidator import XmlMaterialValidator
+except (ImportError, SystemError):
+ import XmlMaterialValidator # type: ignore # This fixes the tests not being able to import.
## Handles serializing and deserializing material containers from an XML file
@@ -40,11 +44,11 @@ class XmlMaterialProfile(InstanceContainer):
#
# \param xml_version: The version number found in an XML file.
# \return The corresponding setting_version.
- @classmethod
- def xmlVersionToSettingVersion(cls, xml_version: str) -> int:
+ @staticmethod
+ def xmlVersionToSettingVersion(xml_version: str) -> int:
if xml_version == "1.3":
return CuraApplication.SettingVersion
- return 0 #Older than 1.3.
+ return 0 # Older than 1.3.
def getInheritedFiles(self):
return self._inherited_files
@@ -63,28 +67,28 @@ class XmlMaterialProfile(InstanceContainer):
Logger.log("w", "Can't change metadata {key} of material {material_id} because it's read-only.".format(key = key, material_id = self.getId()))
return
- # Prevent recursion
- if not apply_to_all:
- super().setMetaDataEntry(key, value)
- return
+ # Some metadata such as diameter should also be instantiated to be a setting. Go though all values for the
+ # "properties" field and apply the new values to SettingInstances as well.
+ new_setting_values_dict = {}
+ if key == "properties":
+ for k, v in value.items():
+ if k in self.__material_properties_setting_map:
+ new_setting_values_dict[self.__material_properties_setting_map[k]] = v
- # Get the MaterialGroup
- material_manager = CuraApplication.getInstance().getMaterialManager()
- root_material_id = self.getMetaDataEntry("base_file") #if basefile is self.getId, this is a basefile.
- material_group = material_manager.getMaterialGroup(root_material_id)
- if not material_group: #If the profile is not registered in the registry but loose/temporary, it will not have a base file tree.
- super().setMetaDataEntry(key, value)
- return
- # Update the root material container
- root_material_container = material_group.root_material_node.getContainer()
- if root_material_container is not None:
- root_material_container.setMetaDataEntry(key, value, apply_to_all = False)
+ if not apply_to_all: # Historical: If you only want to modify THIS container. We only used that to prevent recursion but with the below code that's no longer necessary.
+ # CURA-6920: This is an optimization, but it also fixes the problem that you can only set metadata for a
+ # material container that can be found in the container registry.
+ container_query = [self]
+ else:
+ container_query = registry.findContainers(base_file = self.getMetaDataEntry("base_file"))
- # Update all containers derived from it
- for node in material_group.derived_material_node_list:
- container = node.getContainer()
- if container is not None:
- container.setMetaDataEntry(key, value, apply_to_all = False)
+ for container in container_query:
+ if key not in container.getMetaData() or container.getMetaData()[key] != value:
+ container.getMetaData()[key] = value
+ container.setDirty(True)
+ container.metaDataChanged.emit(container)
+ for k, v in new_setting_values_dict.items():
+ self.setProperty(k, "value", v)
## Overridden from InstanceContainer, similar to setMetaDataEntry.
# without this function the setName would only set the name of the specific nozzle / material / machine combination container
@@ -144,7 +148,7 @@ class XmlMaterialProfile(InstanceContainer):
# setting_version is derived from the "version" tag in the schema, so don't serialize it into a file
if ignored_metadata_keys is None:
ignored_metadata_keys = set()
- ignored_metadata_keys |= {"setting_version", "definition", "status", "variant", "type", "base_file", "approximate_diameter", "id", "container_type", "name"}
+ ignored_metadata_keys |= {"setting_version", "definition", "status", "variant", "type", "base_file", "approximate_diameter", "id", "container_type", "name", "compatible"}
# remove the keys that we want to ignore in the metadata
for key in ignored_metadata_keys:
if key in metadata:
@@ -174,13 +178,16 @@ class XmlMaterialProfile(InstanceContainer):
## End Name Block
for key, value in metadata.items():
- builder.start(key) # type: ignore
+ key_to_use = key
+ if key in self._metadata_tags_that_have_cura_namespace:
+ key_to_use = "cura:" + key_to_use
+ builder.start(key_to_use) # type: ignore
if value is not None: #Nones get handled well by the builder.
#Otherwise the builder always expects a string.
#Deserialize expects the stringified version.
value = str(value)
builder.data(value)
- builder.end(key)
+ builder.end(key_to_use)
builder.end("metadata")
## End Metadata Block
@@ -203,10 +210,8 @@ class XmlMaterialProfile(InstanceContainer):
for instance in self.findInstances():
self._addSettingElement(builder, instance)
- machine_container_map = {} # type: Dict[str, InstanceContainer]
- machine_variant_map = {} # type: Dict[str, Dict[str, Any]]
-
- variant_manager = CuraApplication.getInstance().getVariantManager()
+ machine_container_map = {} # type: Dict[str, InstanceContainer]
+ machine_variant_map = {} # type: Dict[str, Dict[str, Any]]
root_material_id = self.getMetaDataEntry("base_file") # if basefile is self.getId, this is a basefile.
all_containers = registry.findInstanceContainers(base_file = root_material_id)
@@ -223,13 +228,13 @@ class XmlMaterialProfile(InstanceContainer):
machine_variant_map[definition_id] = {}
variant_name = container.getMetaDataEntry("variant_name")
- if variant_name:
- variant_dict = {"variant_node": variant_manager.getVariantNode(definition_id, variant_name),
- "material_container": container}
- machine_variant_map[definition_id][variant_name] = variant_dict
+ if not variant_name:
+ machine_container_map[definition_id] = container
continue
- machine_container_map[definition_id] = container
+ variant_dict = {"variant_type": container.getMetaDataEntry("hardware_type", "nozzle"),
+ "material_container": container}
+ machine_variant_map[definition_id][variant_name] = variant_dict
# Map machine human-readable names to IDs
product_id_map = self.getProductIdMap()
@@ -262,8 +267,7 @@ class XmlMaterialProfile(InstanceContainer):
# Find all hotend sub-profiles corresponding to this material and machine and add them to this profile.
buildplate_dict = {} # type: Dict[str, Any]
for variant_name, variant_dict in machine_variant_map[definition_id].items():
- variant_type = variant_dict["variant_node"].getMetaDataEntry("hardware_type", str(VariantType.NOZZLE))
- variant_type = VariantType(variant_type)
+ variant_type = VariantType(variant_dict["variant_type"])
if variant_type == VariantType.NOZZLE:
# The hotend identifier is not the containers name, but its "name".
builder.start("hotend", {"id": variant_name})
@@ -326,7 +330,7 @@ class XmlMaterialProfile(InstanceContainer):
stream = io.BytesIO()
tree = ET.ElementTree(root)
# this makes sure that the XML header states encoding="utf-8"
- tree.write(stream, encoding = "utf-8", xml_declaration=True)
+ tree.write(stream, encoding = "utf-8", xml_declaration = True)
return stream.getvalue().decode("utf-8")
@@ -390,7 +394,8 @@ class XmlMaterialProfile(InstanceContainer):
self._combineElement(self._expandMachinesXML(result), self._expandMachinesXML(second))
return result
- def _createKey(self, element):
+ @staticmethod
+ def _createKey(element):
key = element.tag.split("}")[-1]
if "key" in element.attrib:
key += " key:" + element.attrib["key"]
@@ -406,15 +411,15 @@ class XmlMaterialProfile(InstanceContainer):
# Recursively merges XML elements. Updates either the text or children if another element is found in first.
# If it does not exist, copies it from second.
- def _combineElement(self, first, second):
+ @staticmethod
+ def _combineElement(first, second):
# Create a mapping from tag name to element.
-
mapping = {}
for element in first:
- key = self._createKey(element)
+ key = XmlMaterialProfile._createKey(element)
mapping[key] = element
for element in second:
- key = self._createKey(element)
+ key = XmlMaterialProfile._createKey(element)
if len(element): # Check if element has children.
try:
if "setting" in element.tag and not "settings" in element.tag:
@@ -424,7 +429,7 @@ class XmlMaterialProfile(InstanceContainer):
for child in element:
mapping[key].append(child)
else:
- self._combineElement(mapping[key], element) # Multiple elements, handle those.
+ XmlMaterialProfile._combineElement(mapping[key], element) # Multiple elements, handle those.
except KeyError:
mapping[key] = element
first.append(element)
@@ -676,32 +681,6 @@ class XmlMaterialProfile(InstanceContainer):
if is_new_material:
containers_to_add.append(new_material)
- # Find the buildplates compatibility
- buildplates = machine.iterfind("./um:buildplate", self.__namespaces)
- buildplate_map = {}
- buildplate_map["buildplate_compatible"] = {}
- buildplate_map["buildplate_recommended"] = {}
- for buildplate in buildplates:
- buildplate_id = buildplate.get("id")
- if buildplate_id is None:
- continue
-
- variant_manager = CuraApplication.getInstance().getVariantManager()
- variant_node = variant_manager.getVariantNode(machine_id, buildplate_id,
- variant_type = VariantType.BUILD_PLATE)
- if not variant_node:
- continue
-
- _, buildplate_unmapped_settings_dict = self._getSettingsDictForNode(buildplate)
-
- buildplate_compatibility = buildplate_unmapped_settings_dict.get("hardware compatible",
- machine_compatibility)
- buildplate_recommended = buildplate_unmapped_settings_dict.get("hardware recommended",
- machine_compatibility)
-
- buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_compatibility
- buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_recommended
-
hotends = machine.iterfind("./um:hotend", self.__namespaces)
for hotend in hotends:
# The "id" field for hotends in material profiles is actually name
@@ -709,11 +688,6 @@ class XmlMaterialProfile(InstanceContainer):
if hotend_name is None:
continue
- variant_manager = CuraApplication.getInstance().getVariantManager()
- variant_node = variant_manager.getVariantNode(machine_id, hotend_name, VariantType.NOZZLE)
- if not variant_node:
- continue
-
hotend_mapped_settings, hotend_unmapped_settings = self._getSettingsDictForNode(hotend)
hotend_compatibility = hotend_unmapped_settings.get("hardware compatible", machine_compatibility)
@@ -737,9 +711,6 @@ class XmlMaterialProfile(InstanceContainer):
new_hotend_material.getMetaData()["compatible"] = hotend_compatibility
new_hotend_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
new_hotend_material.getMetaData()["definition"] = machine_id
- if buildplate_map["buildplate_compatible"]:
- new_hotend_material.getMetaData()["buildplate_compatible"] = buildplate_map["buildplate_compatible"]
- new_hotend_material.getMetaData()["buildplate_recommended"] = buildplate_map["buildplate_recommended"]
cached_hotend_setting_properties = cached_machine_setting_properties.copy()
cached_hotend_setting_properties.update(hotend_mapped_settings)
@@ -749,63 +720,10 @@ class XmlMaterialProfile(InstanceContainer):
new_hotend_material._dirty = False
if is_new_material:
+ if ContainerRegistry.getInstance().isReadOnly(self.getId()):
+ ContainerRegistry.getInstance().setExplicitReadOnly(new_hotend_material.getId())
containers_to_add.append(new_hotend_material)
- #
- # Build plates in hotend
- #
- buildplates = hotend.iterfind("./um:buildplate", self.__namespaces)
- for buildplate in buildplates:
- # The "id" field for buildplate in material profiles is actually name
- buildplate_name = buildplate.get("id")
- if buildplate_name is None:
- continue
-
- variant_manager = CuraApplication.getInstance().getVariantManager()
- variant_node = variant_manager.getVariantNode(machine_id, buildplate_name, VariantType.BUILD_PLATE)
- if not variant_node:
- continue
-
- buildplate_mapped_settings, buildplate_unmapped_settings = self._getSettingsDictForNode(buildplate)
- buildplate_compatibility = buildplate_unmapped_settings.get("hardware compatible",
- buildplate_map["buildplate_compatible"])
- buildplate_recommended = buildplate_unmapped_settings.get("hardware recommended",
- buildplate_map["buildplate_recommended"])
-
- # Generate container ID for the hotend-and-buildplate-specific material container
- new_hotend_and_buildplate_specific_material_id = new_hotend_specific_material_id + "_" + buildplate_name.replace(" ", "_")
-
- # Same as machine compatibility, keep the derived material containers consistent with the parent material
- if ContainerRegistry.getInstance().isLoaded(new_hotend_and_buildplate_specific_material_id):
- new_hotend_and_buildplate_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_and_buildplate_specific_material_id)[0]
- is_new_material = False
- else:
- new_hotend_and_buildplate_material = XmlMaterialProfile(new_hotend_and_buildplate_specific_material_id)
- is_new_material = True
-
- new_hotend_and_buildplate_material.setMetaData(copy.deepcopy(new_hotend_material.getMetaData()))
- new_hotend_and_buildplate_material.getMetaData()["id"] = new_hotend_and_buildplate_specific_material_id
- new_hotend_and_buildplate_material.getMetaData()["name"] = self.getName()
- new_hotend_and_buildplate_material.getMetaData()["variant_name"] = hotend_name
- new_hotend_and_buildplate_material.getMetaData()["buildplate_name"] = buildplate_name
- new_hotend_and_buildplate_material.setDefinition(machine_id)
- # Don't use setMetadata, as that overrides it for all materials with same base file
- new_hotend_and_buildplate_material.getMetaData()["compatible"] = buildplate_compatibility
- new_hotend_and_buildplate_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
- new_hotend_and_buildplate_material.getMetaData()["definition"] = machine_id
- new_hotend_and_buildplate_material.getMetaData()["buildplate_compatible"] = buildplate_compatibility
- new_hotend_and_buildplate_material.getMetaData()["buildplate_recommended"] = buildplate_recommended
-
- cached_hotend_and_buildplate_setting_properties = cached_hotend_setting_properties.copy()
- cached_hotend_and_buildplate_setting_properties.update(buildplate_mapped_settings)
-
- new_hotend_and_buildplate_material.setCachedValues(cached_hotend_and_buildplate_setting_properties)
-
- new_hotend_and_buildplate_material._dirty = False
-
- if is_new_material:
- containers_to_add.append(new_hotend_and_buildplate_material)
-
# there is only one ID for a machine. Once we have reached here, it means we have already found
# a workable ID for that machine, so there is no need to continue
break
@@ -814,9 +732,9 @@ class XmlMaterialProfile(InstanceContainer):
ContainerRegistry.getInstance().addContainer(container_to_add)
@classmethod
- def _getSettingsDictForNode(cls, node) -> Tuple[dict, dict]:
- node_mapped_settings_dict = dict()
- node_unmapped_settings_dict = dict()
+ def _getSettingsDictForNode(cls, node) -> Tuple[Dict[str, Any], Dict[str, Any]]:
+ node_mapped_settings_dict = dict() # type: Dict[str, Any]
+ node_unmapped_settings_dict = dict() # type: Dict[str, Any]
# Fetch settings in the "um" namespace
um_settings = node.iterfind("./um:setting", cls.__namespaces)
@@ -950,7 +868,7 @@ class XmlMaterialProfile(InstanceContainer):
machine_compatibility = cls._parseCompatibleValue(entry.text)
for identifier in machine.iterfind("./um:machine_identifier", cls.__namespaces):
- machine_id_list = product_id_map.get(identifier.get("product"), [])
+ machine_id_list = product_id_map.get(identifier.get("product", ""), [])
if not machine_id_list:
machine_id_list = cls.getPossibleDefinitionIDsFromName(identifier.get("product"))
@@ -982,7 +900,7 @@ class XmlMaterialProfile(InstanceContainer):
result_metadata.append(new_material_metadata)
buildplates = machine.iterfind("./um:buildplate", cls.__namespaces)
- buildplate_map = {} # type: Dict[str, Dict[str, bool]]
+ buildplate_map = {} # type: Dict[str, Dict[str, bool]]
buildplate_map["buildplate_compatible"] = {}
buildplate_map["buildplate_recommended"] = {}
for buildplate in buildplates:
@@ -1111,8 +1029,8 @@ class XmlMaterialProfile(InstanceContainer):
builder.data(data)
builder.end(tag_name)
- @classmethod
- def _profile_name(cls, material_name, color_name):
+ @staticmethod
+ def _profile_name(material_name, color_name):
if material_name is None:
return "Unknown Material"
if color_name != "Generic":
@@ -1120,8 +1038,8 @@ class XmlMaterialProfile(InstanceContainer):
else:
return material_name
- @classmethod
- def getPossibleDefinitionIDsFromName(cls, name):
+ @staticmethod
+ def getPossibleDefinitionIDsFromName(name):
name_parts = name.lower().split(" ")
merged_name_parts = []
for part in name_parts:
@@ -1159,14 +1077,16 @@ class XmlMaterialProfile(InstanceContainer):
return product_to_id_map
## Parse the value of the "material compatible" property.
- @classmethod
- def _parseCompatibleValue(cls, value: str):
+ @staticmethod
+ def _parseCompatibleValue(value: str):
return value in {"yes", "unknown"}
## Small string representation for debugging.
def __str__(self):
return "".format(my_id = self.getId(), name = self.getName(), base_file = self.getMetaDataEntry("base_file"))
+ _metadata_tags_that_have_cura_namespace = {"pva_compatible", "breakaway_compatible"}
+
# Map XML file setting names to internal names
__material_settings_setting_map = {
"print temperature": "default_material_print_temperature",
@@ -1179,7 +1099,16 @@ class XmlMaterialProfile(InstanceContainer):
"adhesion tendency": "material_adhesion_tendency",
"surface energy": "material_surface_energy",
"shrinkage percentage": "material_shrinkage_percentage",
- }
+ "build volume temperature": "build_volume_temperature",
+ "anti ooze retract position": "material_anti_ooze_retracted_position",
+ "anti ooze retract speed": "material_anti_ooze_retraction_speed",
+ "break preparation position": "material_break_preparation_retracted_position",
+ "break preparation speed": "material_break_preparation_speed",
+ "break preparation temperature": "material_break_preparation_temperature",
+ "break position": "material_break_retracted_position",
+ "break speed": "material_break_speed",
+ "break temperature": "material_break_temperature"
+ } # type: Dict[str, str]
__unmapped_settings = [
"hardware compatible",
"hardware recommended"
diff --git a/plugins/XmlMaterialProfile/plugin.json b/plugins/XmlMaterialProfile/plugin.json
index bb1db82fa4..a8f82d1058 100644
--- a/plugins/XmlMaterialProfile/plugin.json
+++ b/plugins/XmlMaterialProfile/plugin.json
@@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Provides capabilities to read and write XML-based material profiles.",
- "api": "6.0",
+ "api": "7.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/XmlMaterialProfile/product_to_id.json b/plugins/XmlMaterialProfile/product_to_id.json
index 6b78d3fe64..a48eb20a18 100644
--- a/plugins/XmlMaterialProfile/product_to_id.json
+++ b/plugins/XmlMaterialProfile/product_to_id.json
@@ -6,6 +6,7 @@
"Ultimaker 2+": "ultimaker2_plus",
"Ultimaker 3": "ultimaker3",
"Ultimaker 3 Extended": "ultimaker3_extended",
+ "Ultimaker S3": "ultimaker_s3",
"Ultimaker S5": "ultimaker_s5",
"Ultimaker Original": "ultimaker_original",
"Ultimaker Original+": "ultimaker_original_plus",
diff --git a/plugins/XmlMaterialProfile/tests/TestXmlMaterialProfile.py b/plugins/XmlMaterialProfile/tests/TestXmlMaterialProfile.py
new file mode 100644
index 0000000000..1bc19f773a
--- /dev/null
+++ b/plugins/XmlMaterialProfile/tests/TestXmlMaterialProfile.py
@@ -0,0 +1,79 @@
+from unittest.mock import patch, MagicMock
+import sys
+import os
+
+# Prevents error: "PyCapsule_GetPointer called with incorrect name" with conflicting SIP configurations between Arcus and PyQt: Import Arcus and Savitar first!
+import Savitar # Dont remove this line
+import Arcus # No really. Don't. It needs to be there!
+from UM.Qt.QtApplication import QtApplication # QtApplication import is required, even though it isn't used.
+
+import pytest
+import XmlMaterialProfile
+
+def createXmlMaterialProfile(material_id):
+ try:
+ return XmlMaterialProfile.XmlMaterialProfile.XmlMaterialProfile(material_id)
+ except AttributeError:
+ return XmlMaterialProfile.XmlMaterialProfile(material_id)
+
+
+def test_setName():
+ material_1 = createXmlMaterialProfile("herpderp")
+ material_2 = createXmlMaterialProfile("OMGZOMG")
+
+ material_1.getMetaData()["base_file"] = "herpderp"
+ material_2.getMetaData()["base_file"] = "herpderp"
+
+ container_registry = MagicMock()
+ container_registry.isReadOnly = MagicMock(return_value = False)
+ container_registry.findInstanceContainers = MagicMock(return_value = [material_1, material_2])
+
+ with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value = container_registry)):
+ material_1.setName("beep!")
+
+ assert material_1.getName() == "beep!"
+ assert material_2.getName() == "beep!"
+
+
+def test_setDirty():
+ material_1 = createXmlMaterialProfile("herpderp")
+ material_2 = createXmlMaterialProfile("OMGZOMG")
+
+ material_1.getMetaData()["base_file"] = "herpderp"
+ material_2.getMetaData()["base_file"] = "herpderp"
+
+ container_registry = MagicMock()
+ container_registry.isReadOnly = MagicMock(return_value=False)
+ container_registry.findContainers = MagicMock(return_value=[material_1, material_2])
+
+ # Sanity check. Since we did a hacky thing to set the metadata, the container should not be dirty.
+ # But this test assumes that it works like that, so we need to validate that.
+ assert not material_1.isDirty()
+ assert not material_2.isDirty()
+
+ with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
+ material_2.setDirty(True)
+
+ assert material_1.isDirty()
+ assert material_2.isDirty()
+
+ # Setting the base material dirty does not set it's child as dirty.
+ with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
+ material_1.setDirty(False)
+
+ assert not material_1.isDirty()
+ assert material_2.isDirty()
+
+
+def test_serializeNonBaseMaterial():
+ material_1 = createXmlMaterialProfile("herpderp")
+ material_1.getMetaData()["base_file"] = "omgzomg"
+
+ container_registry = MagicMock()
+ container_registry.isReadOnly = MagicMock(return_value=False)
+ container_registry.findContainers = MagicMock(return_value=[material_1])
+
+ with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
+ with pytest.raises(NotImplementedError):
+ # This material is not a base material, so it can't be serialized!
+ material_1.serialize()
diff --git a/public_key.pem b/public_key.pem
new file mode 100644
index 0000000000..d07bb5477a
--- /dev/null
+++ b/public_key.pem
@@ -0,0 +1,13 @@
+-----BEGIN RSA PUBLIC KEY-----
+MIICCgKCAgEA8k8IJsNNM097VM2pJ5vxkHcLhHf76JCB0iyvqpUuIgl8Zcp78Go+
+WtVkbVBZPPfSSB8GwjEtxvZeWj3i6e3nfreuuzq2sw6Gh860wMiQbNgL+rYCU3m9
+XxvC0kXgZt+oYs13N5LTePV7BG4goa/JOcN8dsu2ptZKfgH6TPhwshMeOGr/RoGr
+Jw1DrpvVeq/yTkrEHQHdtHr81GDghfK1vzxYQCt94MOFQCeShhtIC/jHelenJA94
+EpXqcWwCzFDfCQ3aXmCNHnMAsTHer7DWDfvsaUFyvJznrxkuQZIOQydGCNWhePTw
+nGiaMydchknr9TT3F+W/yuCs4u5GdZsz7S+1qbG4hblXo6dV6CTzkdKhh/MzONPC
+w6u1QBHUeTWN98zcTdtGIn53jjZEyYTodPnw/p4xLHVCju78a7uwm5U0rahcs6gw
+658glo3uT41mmTrXTBIVTV+4f/dSrwJVpNfTy/E4wi6fiuFeN8ojqXqN+NbIymfJ
+aKar/Jf/nM3QpEYaPz7yyn8PW8MZ7iomqnsPzyQGE1aymuEbw0ipTzMB7Oy/DfuU
+d4JU8FFuVuWJj3zNaXW7U/ggzbt5vkdIP/VNVfNZf741J/yKRbCI0+j4mthbruVQ
+Ka4aB2EVp1ozisHMaALg5tAeUgrQDZjGnVmSQLt+yFUUbG4e0XFQBb8CAwEAAQ==
+-----END RSA PUBLIC KEY-----
diff --git a/resources/bundled_packages/cura.json b/resources/bundled_packages/cura.json
index 9e126ee028..22642cd38e 100644
--- a/resources/bundled_packages/cura.json
+++ b/resources/bundled_packages/cura.json
@@ -6,7 +6,7 @@
"display_name": "3MF Reader",
"description": "Provides support for reading 3MF files.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -23,7 +23,7 @@
"display_name": "3MF Writer",
"description": "Provides support for writing 3MF files.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -33,18 +33,18 @@
}
}
},
- "ChangeLogPlugin": {
+ "AMFReader": {
"package_info": {
- "package_id": "ChangeLogPlugin",
+ "package_id": "AMFReader",
"package_type": "plugin",
- "display_name": "Change Log",
- "description": "Shows changes since latest checked version.",
- "package_version": "1.0.1",
- "sdk_version": "6.0",
+ "display_name": "AMF Reader",
+ "description": "Provides support for reading AMF files.",
+ "package_version": "1.0.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "UltimakerPackages",
- "display_name": "Ultimaker B.V.",
+ "author_id": "fieldOfView",
+ "display_name": "fieldOfView",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
}
@@ -57,7 +57,7 @@
"display_name": "Cura Backups",
"description": "Backup and restore your configuration.",
"package_version": "1.2.0",
- "sdk_version": 6,
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -74,7 +74,7 @@
"display_name": "CuraEngine Backend",
"description": "Provides the link to the CuraEngine slicing backend.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -91,7 +91,7 @@
"display_name": "Cura Profile Reader",
"description": "Provides support for importing Cura profiles.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -108,7 +108,7 @@
"display_name": "Cura Profile Writer",
"description": "Provides support for exporting Cura profiles.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -125,7 +125,7 @@
"display_name": "Firmware Update Checker",
"description": "Checks for firmware updates.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -142,7 +142,7 @@
"display_name": "Firmware Updater",
"description": "Provides a machine actions for updating firmware.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -159,7 +159,7 @@
"display_name": "Compressed G-code Reader",
"description": "Reads g-code from a compressed archive.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -176,7 +176,7 @@
"display_name": "Compressed G-code Writer",
"description": "Writes g-code to a compressed archive.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -193,7 +193,7 @@
"display_name": "G-Code Profile Reader",
"description": "Provides support for importing profiles from g-code files.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -210,7 +210,7 @@
"display_name": "G-Code Reader",
"description": "Allows loading and displaying G-code files.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "VictorLarchenko",
@@ -227,7 +227,7 @@
"display_name": "G-Code Writer",
"description": "Writes g-code to a file.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -244,7 +244,7 @@
"display_name": "Image Reader",
"description": "Enables ability to generate printable geometry from 2D image files.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -261,7 +261,7 @@
"display_name": "Legacy Cura Profile Reader",
"description": "Provides support for importing profiles from legacy Cura versions.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -278,7 +278,7 @@
"display_name": "Machine Settings Action",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "fieldOfView",
@@ -295,7 +295,7 @@
"display_name": "Model Checker",
"description": "Checks models and print configuration for possible printing issues and give suggestions.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -312,7 +312,7 @@
"display_name": "Monitor Stage",
"description": "Provides a monitor stage in Cura.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -329,7 +329,7 @@
"display_name": "Per-Object Settings Tool",
"description": "Provides the per-model settings.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -346,7 +346,7 @@
"display_name": "Post Processing",
"description": "Extension that allows for user created scripts for post processing.",
"package_version": "2.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -363,7 +363,7 @@
"display_name": "Prepare Stage",
"description": "Provides a prepare stage in Cura.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -380,7 +380,7 @@
"display_name": "Preview Stage",
"description": "Provides a preview stage in Cura.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -397,7 +397,7 @@
"display_name": "Removable Drive Output Device",
"description": "Provides removable drive hotplugging and writing support.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -414,7 +414,7 @@
"display_name": "Simulation View",
"description": "Provides the Simulation view.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -431,7 +431,7 @@
"display_name": "Slice Info",
"description": "Submits anonymous slice info. Can be disabled through preferences.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -448,7 +448,7 @@
"display_name": "Solid View",
"description": "Provides a normal solid mesh view.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -465,7 +465,24 @@
"display_name": "Support Eraser Tool",
"description": "Creates an eraser mesh to block the printing of support in certain places.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "TrimeshReader": {
+ "package_info": {
+ "package_id": "TrimeshReader",
+ "package_type": "plugin",
+ "display_name": "Trimesh Reader",
+ "description": "Provides support for reading model files.",
+ "package_version": "1.0.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -482,7 +499,24 @@
"display_name": "Toolbox",
"description": "Find, manage and install new Cura packages.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "UFPReader": {
+ "package_info": {
+ "package_id": "UFPReader",
+ "package_type": "plugin",
+ "display_name": "UFP Reader",
+ "description": "Provides support for reading Ultimaker Format Packages.",
+ "package_version": "1.0.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -499,7 +533,7 @@
"display_name": "UFP Writer",
"description": "Provides support for writing Ultimaker Format Packages.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -516,7 +550,7 @@
"display_name": "Ultimaker Machine Actions",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -533,7 +567,7 @@
"display_name": "UM3 Network Printing",
"description": "Manages network connections to Ultimaker 3 printers.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -550,24 +584,7 @@
"display_name": "USB Printing",
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
"package_version": "1.0.2",
- "sdk_version": "6.0",
- "website": "https://ultimaker.com",
- "author": {
- "author_id": "UltimakerPackages",
- "display_name": "Ultimaker B.V.",
- "email": "plugins@ultimaker.com",
- "website": "https://ultimaker.com"
- }
- }
- },
- "UserAgreement": {
- "package_info": {
- "package_id": "UserAgreement",
- "package_type": "plugin",
- "display_name": "User Agreement",
- "description": "Ask the user once if he/she agrees with our license.",
- "package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -584,7 +601,7 @@
"display_name": "Version Upgrade 2.1 to 2.2",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -601,7 +618,7 @@
"display_name": "Version Upgrade 2.2 to 2.4",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -618,7 +635,7 @@
"display_name": "Version Upgrade 2.5 to 2.6",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -635,7 +652,7 @@
"display_name": "Version Upgrade 2.6 to 2.7",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -652,7 +669,7 @@
"display_name": "Version Upgrade 2.7 to 3.0",
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -669,7 +686,7 @@
"display_name": "Version Upgrade 3.0 to 3.1",
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -686,7 +703,7 @@
"display_name": "Version Upgrade 3.2 to 3.3",
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -703,7 +720,7 @@
"display_name": "Version Upgrade 3.3 to 3.4",
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -720,7 +737,7 @@
"display_name": "Version Upgrade 3.4 to 3.5",
"description": "Upgrades configurations from Cura 3.4 to Cura 3.5.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -737,7 +754,7 @@
"display_name": "Version Upgrade 3.5 to 4.0",
"description": "Upgrades configurations from Cura 3.5 to Cura 4.0.",
"package_version": "1.0.0",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -754,7 +771,58 @@
"display_name": "Version Upgrade 4.0 to 4.1",
"description": "Upgrades configurations from Cura 4.0 to Cura 4.1.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "VersionUpgrade41to42": {
+ "package_info": {
+ "package_id": "VersionUpgrade41to42",
+ "package_type": "plugin",
+ "display_name": "Version Upgrade 4.1 to 4.2",
+ "description": "Upgrades configurations from Cura 4.1 to Cura 4.2.",
+ "package_version": "1.0.0",
+ "sdk_version": "7.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "VersionUpgrade42to43": {
+ "package_info": {
+ "package_id": "VersionUpgrade42to43",
+ "package_type": "plugin",
+ "display_name": "Version Upgrade 4.2 to 4.3",
+ "description": "Upgrades configurations from Cura 4.2 to Cura 4.3.",
+ "package_version": "1.0.0",
+ "sdk_version": "7.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "VersionUpgrade43to44": {
+ "package_info": {
+ "package_id": "VersionUpgrade43to44",
+ "package_type": "plugin",
+ "display_name": "Version Upgrade 4.3 to 4.4",
+ "description": "Upgrades configurations from Cura 4.3 to Cura 4.4.",
+ "package_version": "1.0.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -771,7 +839,7 @@
"display_name": "X3D Reader",
"description": "Provides support for reading X3D files.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "SevaAlekseyev",
@@ -788,7 +856,7 @@
"display_name": "XML Material Profiles",
"description": "Provides capabilities to read and write XML-based material profiles.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -805,7 +873,7 @@
"display_name": "X-Ray View",
"description": "Provides the X-Ray view.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
@@ -822,7 +890,7 @@
"display_name": "Generic ABS",
"description": "The generic ABS profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -840,7 +908,7 @@
"display_name": "Generic BAM",
"description": "The generic BAM profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -858,7 +926,7 @@
"display_name": "Generic CFF CPE",
"description": "The generic CFF CPE profile which other profiles can be based upon.",
"package_version": "1.1.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -876,7 +944,7 @@
"display_name": "Generic CFF PA",
"description": "The generic CFF PA profile which other profiles can be based upon.",
"package_version": "1.1.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -894,7 +962,7 @@
"display_name": "Generic CPE",
"description": "The generic CPE profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -912,7 +980,7 @@
"display_name": "Generic CPE+",
"description": "The generic CPE+ profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -930,7 +998,7 @@
"display_name": "Generic GFF CPE",
"description": "The generic GFF CPE profile which other profiles can be based upon.",
"package_version": "1.1.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -948,7 +1016,7 @@
"display_name": "Generic GFF PA",
"description": "The generic GFF PA profile which other profiles can be based upon.",
"package_version": "1.1.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -966,7 +1034,7 @@
"display_name": "Generic HIPS",
"description": "The generic HIPS profile which other profiles can be based upon.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -984,7 +1052,7 @@
"display_name": "Generic Nylon",
"description": "The generic Nylon profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1002,7 +1070,7 @@
"display_name": "Generic PC",
"description": "The generic PC profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1020,7 +1088,7 @@
"display_name": "Generic PETG",
"description": "The generic PETG profile which other profiles can be based upon.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1038,7 +1106,7 @@
"display_name": "Generic PLA",
"description": "The generic PLA profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1056,7 +1124,7 @@
"display_name": "Generic PP",
"description": "The generic PP profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1074,7 +1142,7 @@
"display_name": "Generic PVA",
"description": "The generic PVA profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1092,7 +1160,7 @@
"display_name": "Generic Tough PLA",
"description": "The generic Tough PLA profile which other profiles can be based upon.",
"package_version": "1.0.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1110,7 +1178,7 @@
"display_name": "Generic TPU",
"description": "The generic TPU profile which other profiles can be based upon.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -1128,7 +1196,7 @@
"display_name": "Dagoma Chromatik PLA",
"description": "Filament testé et approuvé pour les imprimantes 3D Dagoma. Chromatik est l'idéal pour débuter et suivre les tutoriels premiers pas. Il vous offre qualité et résistance pour chacune de vos impressions.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://dagoma.fr/boutique/filaments.html",
"author": {
"author_id": "Dagoma",
@@ -1145,7 +1213,7 @@
"display_name": "FABtotum ABS",
"description": "This material is easy to be extruded but it is not the simplest to use. It is one of the most used in 3D printing to get very well finished objects. It is not sustainable and its smoke can be dangerous if inhaled. The reason to prefer this filament to PLA is mainly because of its precision and mechanical specs. ABS (for plastic) stands for Acrylonitrile Butadiene Styrene and it is a thermoplastic which is widely used in everyday objects. It can be printed with any FFF 3D printer which can get to high temperatures as it must be extruded in a range between 220° and 245°, so it’s compatible with all versions of the FABtotum Personal fabricator.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=40",
"author": {
"author_id": "FABtotum",
@@ -1162,7 +1230,7 @@
"display_name": "FABtotum Nylon",
"description": "When 3D printing started this material was not listed among the extrudable filaments. It is flexible as well as resistant to tractions. It is well known for its uses in textile but also in industries which require a strong and flexible material. There are different kinds of Nylon: 3D printing mostly uses Nylon 6 and Nylon 6.6, which are the most common. It requires higher temperatures to be printed, so a 3D printer must be able to reach them (around 240°C): the FABtotum, of course, can.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=53",
"author": {
"author_id": "FABtotum",
@@ -1179,7 +1247,7 @@
"display_name": "FABtotum PLA",
"description": "It is the most common filament used for 3D printing. It is studied to be bio-degradable as it comes from corn starch’s sugar mainly. It is completely made of renewable sources and has no footprint on polluting. PLA stands for PolyLactic Acid and it is a thermoplastic that today is still considered the easiest material to be 3D printed. It can be extruded at lower temperatures: the standard range of FABtotum’s one is between 185° and 195°.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=39",
"author": {
"author_id": "FABtotum",
@@ -1196,7 +1264,7 @@
"display_name": "FABtotum TPU Shore 98A",
"description": "",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=66",
"author": {
"author_id": "FABtotum",
@@ -1213,7 +1281,7 @@
"display_name": "Fiberlogy HD PLA",
"description": "With our HD PLA you have many more options. You can use this material in two ways. Choose the one you like best. You can use it as a normal PLA and get prints characterized by a very good adhesion between the layers and high precision. You can also make your prints acquire similar properties to that of ABS – better impact resistance and high temperature resistance. All you need is an oven. Yes, an oven! By annealing our HD PLA in an oven, in accordance with the manual, you will avoid all the inconveniences of printing with ABS, such as unpleasant odour or hazardous fumes.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://fiberlogy.com/en/fiberlogy-filaments/filament-hd-pla/",
"author": {
"author_id": "Fiberlogy",
@@ -1230,7 +1298,7 @@
"display_name": "Filo3D PLA",
"description": "Fast, safe and reliable printing. PLA is ideal for the fast and reliable printing of parts and prototypes with a great surface quality.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://dagoma.fr",
"author": {
"author_id": "Dagoma",
@@ -1247,7 +1315,7 @@
"display_name": "IMADE3D JellyBOX PETG",
"description": "",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://shop.imade3d.com/filament.html",
"author": {
"author_id": "IMADE3D",
@@ -1264,7 +1332,7 @@
"display_name": "IMADE3D JellyBOX PLA",
"description": "",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://shop.imade3d.com/filament.html",
"author": {
"author_id": "IMADE3D",
@@ -1281,7 +1349,7 @@
"display_name": "Octofiber PLA",
"description": "PLA material from Octofiber.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://nl.octofiber.com/3d-printing-filament/pla.html",
"author": {
"author_id": "Octofiber",
@@ -1298,7 +1366,7 @@
"display_name": "PolyFlex™ PLA",
"description": "PolyFlex™ is a highly flexible yet easy to print 3D printing material. Featuring good elasticity and a large strain-to- failure, PolyFlex™ opens up a completely new realm of applications.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://www.polymaker.com/shop/polyflex/",
"author": {
"author_id": "Polymaker",
@@ -1315,7 +1383,7 @@
"display_name": "PolyMax™ PLA",
"description": "PolyMax™ PLA is a 3D printing material with excellent mechanical properties and printing quality. PolyMax™ PLA has an impact resistance of up to nine times that of regular PLA, and better overall mechanical properties than ABS.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://www.polymaker.com/shop/polymax/",
"author": {
"author_id": "Polymaker",
@@ -1332,7 +1400,7 @@
"display_name": "PolyPlus™ PLA True Colour",
"description": "PolyPlus™ PLA is a premium PLA designed for all desktop FDM/FFF 3D printers. It is produced with our patented Jam-Free™ technology that ensures consistent extrusion and prevents jams.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://www.polymaker.com/shop/polyplus-true-colour/",
"author": {
"author_id": "Polymaker",
@@ -1349,7 +1417,7 @@
"display_name": "PolyWood™ PLA",
"description": "PolyWood™ is a wood mimic printing material that contains no actual wood ensuring a clean Jam-Free™ printing experience.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "http://www.polymaker.com/shop/polywood/",
"author": {
"author_id": "Polymaker",
@@ -1366,7 +1434,7 @@
"display_name": "Ultimaker ABS",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
"author_id": "UltimakerPackages",
@@ -1385,7 +1453,7 @@
"display_name": "Ultimaker Breakaway",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/breakaway",
"author": {
"author_id": "UltimakerPackages",
@@ -1404,7 +1472,7 @@
"display_name": "Ultimaker CPE",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
"author_id": "UltimakerPackages",
@@ -1423,7 +1491,7 @@
"display_name": "Ultimaker CPE+",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/cpe",
"author": {
"author_id": "UltimakerPackages",
@@ -1442,7 +1510,7 @@
"display_name": "Ultimaker Nylon",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
"author_id": "UltimakerPackages",
@@ -1461,7 +1529,7 @@
"display_name": "Ultimaker PC",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/pc",
"author": {
"author_id": "UltimakerPackages",
@@ -1480,7 +1548,7 @@
"display_name": "Ultimaker PLA",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
"author_id": "UltimakerPackages",
@@ -1499,7 +1567,7 @@
"display_name": "Ultimaker PP",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/pp",
"author": {
"author_id": "UltimakerPackages",
@@ -1518,7 +1586,7 @@
"display_name": "Ultimaker PVA",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
"author_id": "UltimakerPackages",
@@ -1537,7 +1605,7 @@
"display_name": "Ultimaker TPU 95A",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.2.2",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/tpu-95a",
"author": {
"author_id": "UltimakerPackages",
@@ -1556,7 +1624,7 @@
"display_name": "Ultimaker Tough PLA",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.0.3",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://ultimaker.com/products/materials/tough-pla",
"author": {
"author_id": "UltimakerPackages",
@@ -1575,7 +1643,7 @@
"display_name": "Vertex Delta ABS",
"description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1592,7 +1660,7 @@
"display_name": "Vertex Delta PET",
"description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1609,7 +1677,7 @@
"display_name": "Vertex Delta PLA",
"description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1626,7 +1694,7 @@
"display_name": "Vertex Delta TPU",
"description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.0.1",
- "sdk_version": "6.0",
+ "sdk_version": "7.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1636,4 +1704,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/resources/definitions/101Hero.def.json b/resources/definitions/101Hero.def.json
index d77f01fd82..d356d15da9 100644
--- a/resources/definitions/101Hero.def.json
+++ b/resources/definitions/101Hero.def.json
@@ -34,11 +34,10 @@
},
"speed_print": { "default_value": 14 },
"speed_travel": { "value": "speed_print" },
- "speed_infill": { "default_value": 14 },
"speed_wall": { "value": "speed_print * 0.7" },
"speed_topbottom": { "value": "speed_print * 0.7" },
"speed_layer_0": { "value": "speed_print * 0.7" },
- "gantry_height": { "default_value": 0 },
+ "gantry_height": { "value": "0" },
"retraction_speed": { "default_value" : 10 },
"retraction_amount": { "default_value" : 2.5 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
diff --git a/resources/definitions/3dator.def.json b/resources/definitions/3dator.def.json
index e91c46920b..ac37523379 100644
--- a/resources/definitions/3dator.def.json
+++ b/resources/definitions/3dator.def.json
@@ -17,15 +17,10 @@
"overrides": {
"machine_name": { "default_value": "3Dator" },
- "speed_travel": { "default_value": 120 },
"prime_tower_size": { "default_value": 8.660254037844387 },
"infill_sparse_density": { "default_value": 20 },
- "speed_wall_x": { "default_value": 45 },
- "speed_wall_0": { "default_value": 40 },
- "speed_topbottom": { "default_value": 35 },
"layer_height": { "default_value": 0.2 },
"speed_print": { "default_value": 50 },
- "speed_infill": { "default_value": 60 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
"machine_height": { "default_value": 260 },
@@ -33,8 +28,6 @@
"machine_depth": { "default_value": 170 },
"machine_width": { "default_value": 180 },
"retraction_speed": {"default_value":100},
- "cool_fan_speed_min": {"default_value": 20},
- "cool_fan_speed_max": {"default_value": 70},
"adhesion_type": { "default_value": "none" },
"machine_head_with_fans_polygon": {
"default_value": [
@@ -45,7 +38,7 @@
]
},
"gantry_height": {
- "default_value": 30
+ "value": "30"
},
"machine_start_gcode": {
"default_value": ";Sliced at: {day} {date} {time}\nM104 S{material_print_temperature} ;set temperatures\nM140 S{material_bed_temperature}\nM109 S{material_print_temperature} ;wait for temperatures\nM190 S{material_bed_temperature}\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 Z0 ;move Z to min endstops\nG28 X0 Y0 ;move X/Y to min endstops\nG29 ;Auto Level\nG1 Z0.6 F{speed_travel} ;move the Nozzle near the Bed\nG92 E0\nG1 Y0 ;zero the extruded length\nG1 X10 E30 F500 ;printing a Line from right to left\nG92 E0 ;zero the extruded length again\nG1 Z2\nG1 F{speed_travel}\nM117 Printing...;Put printing message on LCD screen\nM150 R255 U255 B255 P4 ;Change LED Color to white" },
diff --git a/resources/definitions/Mark2_for_Ultimaker2.def.json b/resources/definitions/Mark2_for_Ultimaker2.def.json
new file mode 100644
index 0000000000..1aca2a3844
--- /dev/null
+++ b/resources/definitions/Mark2_for_Ultimaker2.def.json
@@ -0,0 +1,214 @@
+{
+ "version": 2,
+ "name": "Mark2 for Ultimaker2",
+ "inherits": "ultimaker2_plus",
+ "metadata": {
+ "visible": true,
+ "author": "TheUltimakerCommunity",
+ "manufacturer": "Foehnsturm",
+ "category": "Other",
+ "weight": 0,
+ "has_variants": true,
+ "has_materials": true,
+ "has_machine_quality": false,
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker.png",
+ "platform": "ultimaker2_platform.obj",
+ "platform_texture": "Mark2_for_Ultimaker2_backplate.png",
+ "machine_extruder_trains":
+ {
+ "0": "Mark2_extruder1",
+ "1": "Mark2_extruder2"
+ },
+ "supported_actions": ["MachineSettingsAction", "UpgradeFirmware"]
+ },
+ "overrides": {
+ "machine_name": { "default_value": "Mark2_for_Ultimaker2" },
+ "machine_width": {
+ "default_value": 223
+ },
+ "machine_depth": {
+ "default_value": 223
+ },
+ "machine_height": {
+ "default_value": 203
+ },
+ "gantry_height": {
+ "value": "52"
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_heat_up_speed": {
+ "default_value": 3.5
+ },
+ "machine_nozzle_cool_down_speed": {
+ "default_value": 1.5
+ },
+ "machine_min_cool_heat_time_window":
+ {
+ "default_value": 15.0
+ },
+ "machine_show_variants": {
+ "default_value": true
+ },
+ "machine_nozzle_head_distance": {
+ "default_value": 5
+ },
+ "machine_nozzle_expansion_angle": {
+ "default_value": 45
+ },
+ "machine_heat_zone_length": {
+ "default_value": 20
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "speed_infill": {
+ "value": "speed_print"
+ },
+ "speed_wall_x": {
+ "value": "speed_wall"
+ },
+ "layer_height_0": {
+ "value": "round(machine_nozzle_size / 1.5, 2)"
+ },
+ "line_width": {
+ "value": "round(machine_nozzle_size * 0.875, 2)"
+ },
+ "speed_support": {
+ "value": "speed_wall_0"
+ },
+ "machine_max_feedrate_x": {
+ "default_value": 250
+ },
+ "machine_max_feedrate_y": {
+ "default_value": 250
+ },
+ "machine_max_feedrate_z": {
+ "default_value": 40
+ },
+ "machine_max_feedrate_e": {
+ "default_value": 45
+ },
+ "machine_acceleration": {
+ "default_value": 3000
+ },
+ "retraction_amount": {
+ "default_value": 5.1
+ },
+ "retraction_speed": {
+ "default_value": 25
+ },
+ "switch_extruder_retraction_amount": {
+ "value": "retraction_amount",
+ "enabled": false
+ },
+ "switch_extruder_retraction_speeds": {
+ "value": "retraction_speed",
+ "enabled": false
+ },
+ "switch_extruder_retraction_speed": {
+ "value": "retraction_retract_speed",
+ "enabled": false
+ },
+ "switch_extruder_prime_speed": {
+ "value": "retraction_prime_speed",
+ "enabled": false
+ },
+ "machine_head_with_fans_polygon":
+ {
+ "default_value": [
+ [ -44, 14 ],
+ [ -44, -34 ],
+ [ 64, 14 ],
+ [ 64, -34 ]
+ ]
+ },
+ "machine_use_extruder_offset_to_offset_coords": {
+ "default_value": false
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode" : {
+ "value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"G21 ;metric values\\nG90 ;absolute positioning\\nM82 ;set extruder to absolute mode\\nM107 ;start with the fan off\\nM200 D0 T0 ;reset filament diameter\\nM200 D0 T1\\nG28 Z0; home all\\nG28 X0 Y0\\nG0 Z20 F2400 ;move the platform to 20mm\\nG92 E0\\nM190 S{material_bed_temperature_layer_0}\\nM109 T0 S{material_standby_temperature, 0}\\nM109 T1 S{material_print_temperature_layer_0, 1}\\nM104 T0 S{material_print_temperature_layer_0, 0}\\nT1 ; move to the 2th head\\nG0 Z20 F2400\\nG92 E-7.0 ;prime distance\\nG1 E0 F45 ;purge nozzle\\nG1 E-5.1 F1500 ; retract\\nG1 X90 Z0.01 F5000 ; move away from the prime poop\\nG1 X50 F9000\\nG0 Z20 F2400\\nT0 ; move to the first head\\nM104 T1 S{material_standby_temperature, 1}\\nG0 Z20 F2400\\nM104 T{initial_extruder_nr} S{material_print_temperature_layer_0, initial_extruder_nr}\\nG92 E-7.0\\nG1 E0 F45 ;purge nozzle\\nG1 X60 Z0.01 F5000 ; move away from the prime poop\\nG1 X20 F9000\\nM400 ;finish all moves\\nG92 E0\\n;end of startup sequence\\n\""
+ },
+ "machine_end_gcode" : {
+ "value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"G90 ;absolute positioning\\nM104 S0 T0 ;extruder heater off\\nM104 S0 T1\\nM140 S0 ;turn off bed\\nT0 ; move to the first head\\nM107 ;fan off\""
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ },
+ "acceleration_enabled":
+ {
+ "default_value": true
+ },
+ "acceleration_print":
+ {
+ "value": "2000"
+ },
+ "acceleration_travel":
+ {
+ "value": "acceleration_print if magic_spiralize else 3000"
+ },
+ "acceleration_layer_0": { "value": "acceleration_topbottom" },
+ "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
+ "acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
+ "acceleration_support_interface": { "value": "acceleration_topbottom" },
+ "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 500 / 4000)" },
+ "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 4000)" },
+ "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 500 / 1000)" },
+ "jerk_enabled":
+ {
+ "default_value": true
+ },
+ "jerk_print":
+ {
+ "default_value": 12
+ },
+ "jerk_travel":
+ {
+ "value": "jerk_print if magic_spiralize else 20"
+ },
+ "jerk_layer_0": { "value": "jerk_topbottom" },
+ "jerk_prime_tower": { "value": "10 if jerk_print < 16 else math.ceil(jerk_print * 15 / 25)" },
+ "jerk_support": { "value": "10 if jerk_print < 16 else math.ceil(jerk_print * 15 / 25)" },
+ "jerk_support_interface": { "value": "jerk_topbottom" },
+ "jerk_topbottom": { "value": "10 if jerk_print < 25 else math.ceil(jerk_print * 10 / 25)" },
+ "jerk_wall": { "value": "10 if jerk_print < 16 else math.ceil(jerk_print * 15 / 25)" },
+ "jerk_wall_0": { "value": "10 if jerk_wall < 16 else math.ceil(jerk_wall * 6 / 10)" },
+ "jerk_travel_layer_0": { "value": "math.ceil(jerk_layer_0 * jerk_travel / jerk_print)" },
+ "extruder_prime_pos_abs": { "default_value": false },
+ "extruder_prime_pos_x": { "default_value": 0.0, "enabled": false },
+ "extruder_prime_pos_y": { "default_value": 0.0, "enabled": false },
+ "extruder_prime_pos_z": { "default_value": 0.0, "enabled": false },
+ "layer_start_x":
+ {
+ "default_value": 105.0,
+ "enabled": false
+ },
+ "layer_start_y":
+ {
+ "default_value": 27.0,
+ "enabled": false
+ },
+ "prime_tower_position_x": {
+ "value": "185"
+ },
+ "prime_tower_position_y": {
+ "value": "160"
+ },
+ "machine_disallowed_areas": {
+ "default_value": [
+ [[-115, 112.5], [ -10, 112.5], [ -10, 72.5], [-115, 72.5]],
+ [[ 115, 112.5], [ 115, 72.5], [ 15, 72.5], [ 15, 112.5]],
+ [[-115, -112.5], [-115, -87.5], [ 115, -87.5], [ 115, -112.5]],
+ [[-115, 72.5], [-97, 72.5], [-97, -112.5], [-115, -112.5]]
+ ]
+ }
+ }
+}
diff --git a/resources/definitions/abax_pri3.def.json b/resources/definitions/abax_pri3.def.json
index 1ab48b865a..529636be90 100644
--- a/resources/definitions/abax_pri3.def.json
+++ b/resources/definitions/abax_pri3.def.json
@@ -49,33 +49,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
- "material_print_temperature": {
- "default_value": 200
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 70
- },
- "speed_wall": {
- "default_value": 25
- },
- "speed_topbottom": {
- "default_value": 15
- },
- "speed_travel": {
- "default_value": 150
- },
- "speed_layer_0": {
- "default_value": 30
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/abax_pri5.def.json b/resources/definitions/abax_pri5.def.json
index 46229ce756..9e4e7e3b20 100644
--- a/resources/definitions/abax_pri5.def.json
+++ b/resources/definitions/abax_pri5.def.json
@@ -49,33 +49,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
- "material_print_temperature": {
- "default_value": 200
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 70
- },
- "speed_wall": {
- "default_value": 25
- },
- "speed_topbottom": {
- "default_value": 15
- },
- "speed_travel": {
- "default_value": 150
- },
- "speed_layer_0": {
- "default_value": 30
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/abax_titan.def.json b/resources/definitions/abax_titan.def.json
index 9f67117d6c..98643df22b 100644
--- a/resources/definitions/abax_titan.def.json
+++ b/resources/definitions/abax_titan.def.json
@@ -49,33 +49,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
- "material_print_temperature": {
- "default_value": 200
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 70
- },
- "speed_wall": {
- "default_value": 25
- },
- "speed_topbottom": {
- "default_value": 15
- },
- "speed_travel": {
- "default_value": 150
- },
- "speed_layer_0": {
- "default_value": 30
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/alfawise_u20.def.json b/resources/definitions/alfawise_u20.def.json
index 8a6badeca6..4da42fdb1d 100644
--- a/resources/definitions/alfawise_u20.def.json
+++ b/resources/definitions/alfawise_u20.def.json
@@ -39,7 +39,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 10
+ "value": "10"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -47,12 +47,6 @@
"material_diameter": {
"default_value": 1.75
},
- "material_print_temperature": {
- "default_value": 210
- },
- "material_bed_temperature": {
- "default_value": 50
- },
"layer_height_0": {
"default_value": 0.2
},
@@ -62,21 +56,6 @@
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 20
- },
"support_enable": {
"default_value": true
},
diff --git a/resources/definitions/alfawise_u30.def.json b/resources/definitions/alfawise_u30.def.json
index 65f6adcfe0..e05536f66c 100644
--- a/resources/definitions/alfawise_u30.def.json
+++ b/resources/definitions/alfawise_u30.def.json
@@ -14,80 +14,45 @@
}
},
"overrides": {
- "machine_name": {
- "default_value": "Alfawise U30"
- },
+ "machine_name": { "default_value": "Alfawise U30" },
"machine_start_gcode": {
"default_value": "; -- START GCODE --\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z1 F1000 ;move up slightly\nG1 Y60.0 Z0 E9.0 F1000.0;intro line\nG1 Y100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\nG1 F80\n;Put printing message on LCD screen\nM117 Printing...\n; -- end of START GCODE --"
},
"machine_end_gcode": {
"default_value": "; -- END GCODE --\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F80 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning\nM107 ;turn the fan off; -- end of END GCODE --"
},
- "machine_width": {
- "default_value": 220
- },
- "machine_height": {
- "default_value": 250
- },
- "machine_depth": {
- "default_value": 220
- },
- "machine_heated_bed": {
- "default_value": true
- },
- "machine_center_is_zero": {
- "default_value": false
- },
- "gantry_height": {
- "default_value": 10
- },
- "machine_gcode_flavor": {
- "default_value": "RepRap (Marlin/Sprinter)"
- },
- "material_diameter": {
- "default_value": 1.75
- },
- "material_print_temperature": {
- "default_value": 210
- },
- "material_bed_temperature": {
- "default_value": 50
- },
- "layer_height_0": {
- "default_value": 0.2
- },
- "wall_thickness": {
- "default_value": 1.2
- },
- "speed_print": {
- "default_value": 40
- },
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 20
- },
- "support_enable": {
- "default_value": true
- },
- "retraction_enable": {
- "default_value": true
- },
- "retraction_amount": {
- "default_value": 5
- },
- "retraction_speed": {
- "default_value": 45
- }
+ "material_diameter": { "default_value": 1.75 },
+ "layer_height_0": { "default_value": 0.2 },
+ "wall_thickness": { "default_value": 1.2 },
+ "speed_print": { "default_value": 40 },
+ "support_enable": { "default_value": true },
+ "retraction_enable": { "default_value": true },
+ "retraction_amount": { "default_value": 5 },
+ "retraction_speed": { "default_value": 45 },
+ "gantry_height": { "value": "25" },
+ "machine_width": { "default_value": 220 },
+ "machine_height": { "default_value": 250 },
+ "machine_depth": { "default_value": 220 },
+ "machine_center_is_zero": { "default_value": false },
+ "machine_heated_bed": { "default_value": true },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_max_feedrate_x": { "default_value": 200 },
+ "machine_max_feedrate_y": { "default_value": 200 },
+ "machine_max_feedrate_z": { "default_value": 5 },
+ "machine_max_feedrate_e": { "default_value": 100 },
+ "machine_max_acceleration_x": { "default_value": 500 },
+ "machine_max_acceleration_y": { "default_value": 500 },
+ "machine_max_acceleration_z": { "default_value": 10 },
+ "machine_max_acceleration_e": { "default_value": 3000 },
+ "machine_acceleration": { "default_value": 300 },
+ "machine_max_jerk_xy": { "default_value": 20.0 },
+ "machine_max_jerk_z": { "default_value": 0.4 },
+ "machine_max_jerk_e": { "default_value": 5.0 },
+ "machine_steps_per_mm_x": { "default_value": 80 },
+ "machine_steps_per_mm_y": { "default_value": 80 },
+ "machine_steps_per_mm_z": { "default_value": 400 },
+ "machine_steps_per_mm_e": { "default_value": 93 },
+ "skirt_line_count": { "default_value": 1 },
+ "skirt_brim_minimal_length": { "default_value": 250 }
}
}
diff --git a/resources/definitions/alya3dp.def.json b/resources/definitions/alya3dp.def.json
index e918649097..8de7c79641 100644
--- a/resources/definitions/alya3dp.def.json
+++ b/resources/definitions/alya3dp.def.json
@@ -1,12 +1,22 @@
{
- "name": "ALYA",
"version": 2,
+ "name": "ALYA",
"inherits": "fdmprinter",
- "metadata": {
+ "metadata":
+ {
"visible": true,
"author": "ALYA",
- "manufacturer": "ALYA",
+ "manufacturer": "Kati Hal ARGE",
+ "category": "Other",
"file_formats": "text/x-gcode",
+ "platform": "alya_platform.stl",
+ "platform_offset": [-60, -45, 75 ],
+ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "generic_tpu_175", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla","tizyx_pla","tizyx_abs","tizyx_pla_bois" ],
+ "preferred_material": "generic_pla",
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variants": false,
+ "supports_usb_connection": false,
"machine_extruder_trains":
{
"0": "alya3dp_extruder_0"
@@ -14,37 +24,27 @@
},
"overrides": {
- "machine_width": {
- "default_value": 100
+ "machine_name": { "default_value": "ALYA 3DP" },
+ "machine_heated_bed": { "default_value": false },
+ "machine_width": { "default_value": 100 },
+ "machine_height": { "default_value": 133 },
+ "machine_depth": { "default_value": 100 },
+ "machine_center_is_zero": { "default_value": false },
+ "gantry_height": { "value": "55"},
+ "retraction_amount": { "default_value": 1.5 },
+ "support_enable": { "default_value": true},
+ "machine_head_with_fans_polygon": {
+ "default_value": [[75, 18],[18, 18],[18, 35],[75, 35]]
},
- "machine_height": {
- "default_value": 133
+ "adhesion_type": {"options": {"raft": "Raft" ,"none": "None", "brim": "Brim"}, "default_value": "raft"},
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode":
+ {
+ "default_value": ";Sliced at: {day} {date} {time} \n ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} \n ;Print time: {print_time} \n ;Filament used: {filament_amount}m {filament_weight}g \n ;Filament cost: {filament_cost} \n G28 X0 Y0 ;move X Y to endstops \n G28 Z0 ;move Z to endstops \n ; M190 S{material_bed_temperature} ;bed temp \n M107 ; switch fan off \n M109 S{material_print_temperature} ;extruder temp set \n G1 F3000 \n G1 Z10 \n G92 E0 ;zero the extruded length \n G1 F200 E1 ;extrude 1mm of feed stock \n G92 E0 ;zero the extruded length again \n G4 P7000 ; wait 7000ms \n M117 Printing... ;Put printing message on LCD screen"
},
- "machine_depth": {
- "default_value": 100
- },
- "machine_center_is_zero": {
- "default_value": false
- },
- "machine_head_polygon": {
- "default_value": [
- [75, 18],
- [18, 18],
- [18, 35],
- [75, 35]
- ]
- },
- "gantry_height": {
- "default_value": 55
- },
- "machine_gcode_flavor": {
- "default_value": "RepRap"
- },
- "machine_start_gcode": {
- "default_value": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\n;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line\n;M109 S{print_temperature} ;Uncomment to add your own temperature line\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to max endstops\nG1 Z115.0 F{speed_travel} ;move th e platform up 20mm\nG28 Z0 ;move Z to max endstop\nG1 Z15.0 F{speed_travel} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nM301 H1 P26.38 I2.57 D67.78\n;Put printing message on LCD screen\nM117 Printing..."
- },
- "machine_end_gcode": {
- "default_value": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG28 Z0\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
+ "machine_end_gcode":
+ {
+ "default_value": ";End GCode\nM104 S0 ;extruder heater off \nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG28 Z0\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
}
}
}
\ No newline at end of file
diff --git a/resources/definitions/alyanx3dp.def.json b/resources/definitions/alyanx3dp.def.json
new file mode 100644
index 0000000000..07e0a090a9
--- /dev/null
+++ b/resources/definitions/alyanx3dp.def.json
@@ -0,0 +1,50 @@
+{
+ "version": 2,
+ "name": "ALYA NX",
+ "inherits": "fdmprinter",
+ "metadata":
+ {
+ "visible": true,
+ "author": "ALYA",
+ "manufacturer": "Kati Hal ARGE",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "platform": "alya_nx_platform.stl",
+ "platform_offset": [-104, 0, 93 ],
+ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "generic_tpu_175", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla","tizyx_pla","tizyx_abs","tizyx_pla_bois" ],
+ "preferred_material": "generic_pla",
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variants": false,
+ "supports_usb_connection": false,
+ "machine_extruder_trains":
+ {
+ "0": "alya3dp_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "ALYA NX 3DP" },
+ "machine_heated_bed": { "default_value": false },
+ "machine_width": { "default_value": 180 },
+ "machine_height": { "default_value": 170 },
+ "machine_depth": { "default_value": 160 },
+ "machine_center_is_zero": { "default_value": false },
+ "gantry_height": { "value": "55"},
+ "retraction_amount": { "default_value": 1.5 },
+ "support_enable": { "default_value": true},
+ "machine_head_with_fans_polygon": {
+ "default_value": [[75, 18],[18, 18],[18, 35],[75, 35]]
+ },
+ "adhesion_type": {"options": {"raft": "Raft" ,"none": "None", "brim": "Brim"}, "default_value": "raft"},
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode":
+ {
+ "default_value": ";Sliced at: {day} {date} {time} \n ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} \n ;Print time: {print_time} \n ;Filament used: {filament_amount}m {filament_weight}g \n ;Filament cost: {filament_cost} \n G28 X0 Y0 ;move X Y to endstops \n G28 Z0 ;move Z to endstops \n ; M190 S{material_bed_temperature} ;bed temp \n M107 ; switch fan off \n M109 S{material_print_temperature} ;extruder temp set \n G1 F3000 \n G1 Z10 \n G92 E0 ;zero the extruded length \n G1 F200 E1 ;extrude 1mm of feed stock \n G92 E0 ;zero the extruded length again \n G4 P7000 ; wait 7000ms \n M117 Printing... ;Put printing message on LCD screen"
+ },
+ "machine_end_gcode":
+ {
+ "default_value": ";End GCode\nM104 S0 ;extruder heater off \nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG28 Z0\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/anet_a6.def.json b/resources/definitions/anet_a6.def.json
new file mode 100644
index 0000000000..0f5384451e
--- /dev/null
+++ b/resources/definitions/anet_a6.def.json
@@ -0,0 +1,45 @@
+{
+ "version": 2,
+ "name": "Anet A6",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Mark",
+ "manufacturer": "Anet",
+ "file_formats": "text/x-gcode",
+ "platform": "aneta6_platform.stl",
+ "platform_offset": [0, -3.4, 0],
+ "machine_extruder_trains":
+ {
+ "0": "anet_a6_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Anet A6" },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_width": {
+ "default_value": 220
+ },
+ "machine_height": {
+ "default_value": 250
+ },
+ "machine_depth": {
+ "default_value": 220
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "gantry_height": {
+ "value": "55"
+ },
+ "machine_start_gcode": {
+ "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nM84 ;steppers off\nM0 S12 ;wait 12 seconds\nM17 ;turn steppers on\nG1 Z10.0 F300 ;move the platform down 10mm\nG92 E0 ;zero the extruded length\nG1 F200 E8 ;extrude 8mm of feed stock\nG92 E0 ;zero the extruded length again\nM0 S5 ;wait 5 seconds\nG1 F9000\nM117 Printing..."
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+4 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG1 Y210 F9000 ;move out to get part off\nM84 ;steppers off\nG90 ;absolute positioning"
+ }
+ }
+}
diff --git a/resources/definitions/anycubic_4max.def.json b/resources/definitions/anycubic_4max.def.json
index c14ce1ac31..05fffcb206 100644
--- a/resources/definitions/anycubic_4max.def.json
+++ b/resources/definitions/anycubic_4max.def.json
@@ -50,7 +50,7 @@
"jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" },
"jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" },
- "gantry_height": { "default_value": 25.0 },
+ "gantry_height": { "value": "25.0" },
"skin_overlap": { "value": "10" },
"acceleration_enabled": { "value": "True" },
@@ -83,6 +83,6 @@
"machine_gcode_flavor":{"default_value": "RepRap (Marlin/Sprinter)"},
"machine_start_gcode":{"default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F{speed_travel} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nM117 Printing...\nG5"},
- "machine_end_gcode":{"default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle\nto release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops\nso the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000"}
+ "machine_end_gcode":{"default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops, so the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000"}
}
}
diff --git a/resources/definitions/anycubic_chiron.def.json b/resources/definitions/anycubic_chiron.def.json
index 83c2056d76..1b18a936a7 100644
--- a/resources/definitions/anycubic_chiron.def.json
+++ b/resources/definitions/anycubic_chiron.def.json
@@ -52,7 +52,7 @@
},
"gantry_height":
{
- "default_value": 35
+ "value": "35"
},
"machine_head_with_fans_polygon":
{
diff --git a/resources/definitions/anycubic_i3_mega.def.json b/resources/definitions/anycubic_i3_mega.def.json
index 8a96d98023..18005f0e12 100644
--- a/resources/definitions/anycubic_i3_mega.def.json
+++ b/resources/definitions/anycubic_i3_mega.def.json
@@ -46,7 +46,7 @@
},
"gantry_height":
{
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor":
{
@@ -54,11 +54,11 @@
},
"machine_start_gcode":
{
- "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F{speed_travel} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nM117 Printing...\nG5"
+ "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F{speed_travel} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nG0 Y20 F{speed_travel}\nM117 Printing...\nG5"
},
"machine_end_gcode":
{
- "default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle\nto release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops\nso the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000"
+ "default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops, so the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000"
}
}
}
diff --git a/resources/definitions/bfb.def.json b/resources/definitions/bfb.def.json
index d1dfa9ef1b..e88c8c792b 100644
--- a/resources/definitions/bfb.def.json
+++ b/resources/definitions/bfb.def.json
@@ -15,26 +15,19 @@
},
"overrides": {
- "speed_topbottom": { "default_value": 40 },
"speed_print": { "default_value": 40 },
"machine_extruder_count": { "default_value": 1 },
"prime_tower_size": { "default_value": 7.745966692414834 },
"machine_name": { "default_value": "BFB_Test" },
"machine_heated_bed": { "default_value": false },
- "speed_layer_0": { "default_value": 25 },
"machine_width": { "default_value": 275 },
"machine_gcode_flavor": { "default_value": "BFB" },
"machine_depth": { "default_value": 265 },
- "speed_infill": { "default_value": 30 },
"machine_center_is_zero": { "default_value": true },
"machine_height": { "default_value": 240 },
"layer_height": { "default_value": 0.25 },
- "material_print_temperature": { "default_value": 200 },
"retraction_amount": { "default_value": 0.05 },
- "speed_wall_0": { "default_value": 25 },
- "speed_travel": { "default_value": 50 },
"infill_sparse_density": { "default_value": 10 },
- "layer_height_0": { "default_value": 0.5 },
- "speed_wall_x": { "default_value": 20 }
+ "layer_height_0": { "default_value": 0.5 }
}
}
diff --git a/resources/definitions/bibo2_dual.def.json b/resources/definitions/bibo2_dual.def.json
index 1ae16a49b1..a644185915 100644
--- a/resources/definitions/bibo2_dual.def.json
+++ b/resources/definitions/bibo2_dual.def.json
@@ -1,11 +1,10 @@
{
- "id": "BIBO2 dual",
"version": 2,
"name": "BIBO2 dual",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "author": "na",
+ "author": "unknown",
"manufacturer": "BIBO",
"category": "Other",
"file_formats": "text/x-gcode",
@@ -64,7 +63,7 @@
]
},
"gantry_height": {
- "default_value": 12
+ "value": "12"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -78,14 +77,17 @@
"machine_end_gcode": {
"default_value": ";End GCode\nM104 T0 S0 ;extruder heater off\nM104 T1 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91\nG1 Z1 F100 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-2 X-20 Y-20 F300 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
},
+ "speed_print": {
+ "default_value": 40
+ },
"machine_extruder_count": {
"default_value": 2
},
"prime_tower_position_x": {
- "default_value": 50
+ "value": "50"
},
"prime_tower_position_y": {
- "default_value": 50
+ "value": "50"
}
}
}
diff --git a/resources/definitions/bq_hephestos.def.json b/resources/definitions/bq_hephestos.def.json
index be024cd6fa..d9e84dae87 100644
--- a/resources/definitions/bq_hephestos.def.json
+++ b/resources/definitions/bq_hephestos.def.json
@@ -54,33 +54,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
- "material_print_temperature": {
- "default_value": 220
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 20
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/bq_hephestos_2.def.json b/resources/definitions/bq_hephestos_2.def.json
index 90a86433fb..5c122eb9a4 100644
--- a/resources/definitions/bq_hephestos_2.def.json
+++ b/resources/definitions/bq_hephestos_2.def.json
@@ -24,26 +24,14 @@
"machine_height": { "default_value": 220 },
"machine_heated_bed": { "default_value": false },
"machine_center_is_zero": { "default_value": false },
- "material_print_temperature": { "default_value": 210 },
- "material_bed_temperature": { "default_value": 0 },
"layer_height": { "default_value": 0.2 },
"layer_height_0": { "default_value": 0.2 },
- "wall_line_count": { "default_value": 3 },
"wall_thickness": { "default_value": 1.2 },
"top_bottom_thickness": { "default_value": 1.2 },
"infill_sparse_density": { "default_value": 20 },
- "infill_overlap": { "default_value": 15 },
"speed_print": { "default_value": 60 },
- "speed_travel": { "default_value": 160 },
- "speed_layer_0": { "default_value": 30 },
- "speed_wall_x": { "default_value": 35 },
- "speed_wall_0": { "default_value": 30 },
- "speed_infill": { "default_value": 80 },
- "speed_topbottom": { "default_value": 35 },
- "skirt_brim_speed": { "default_value": 35 },
"skirt_line_count": { "default_value": 4 },
"skirt_brim_minimal_length": { "default_value": 30 },
- "skirt_gap": { "default_value": 6 },
- "cool_fan_full_at_height": { "default_value": 0.4 }
+ "skirt_gap": { "default_value": 6 }
}
}
diff --git a/resources/definitions/bq_hephestos_xl.def.json b/resources/definitions/bq_hephestos_xl.def.json
index a8d63cbb41..16d0953bf1 100644
--- a/resources/definitions/bq_hephestos_xl.def.json
+++ b/resources/definitions/bq_hephestos_xl.def.json
@@ -53,33 +53,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
- "material_print_temperature": {
- "default_value": 220
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 20
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/bq_witbox.def.json b/resources/definitions/bq_witbox.def.json
index b96da6179c..fce2af9f97 100644
--- a/resources/definitions/bq_witbox.def.json
+++ b/resources/definitions/bq_witbox.def.json
@@ -54,33 +54,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
- "material_print_temperature": {
- "default_value": 220
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 20
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/bq_witbox_2.def.json b/resources/definitions/bq_witbox_2.def.json
index 7412647852..d1114aafd6 100644
--- a/resources/definitions/bq_witbox_2.def.json
+++ b/resources/definitions/bq_witbox_2.def.json
@@ -41,21 +41,12 @@
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
- "material_print_temperature": {
- "default_value": 210
- },
- "material_bed_temperature": {
- "default_value": 0
- },
"layer_height": {
"default_value": 0.2
},
"layer_height_0": {
"default_value": 0.2
},
- "wall_line_count": {
- "default_value": 3
- },
"wall_thickness": {
"default_value": 1.2
},
@@ -65,33 +56,9 @@
"infill_sparse_density": {
"default_value": 20
},
- "infill_overlap": {
- "default_value": 15
- },
"speed_print": {
"default_value": 60
},
- "speed_travel": {
- "default_value": 160
- },
- "speed_layer_0": {
- "default_value": 30
- },
- "speed_wall_x": {
- "default_value": 35
- },
- "speed_wall_0": {
- "default_value": 30
- },
- "speed_infill": {
- "default_value": 80
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "skirt_brim_speed": {
- "default_value": 35
- },
"skirt_line_count": {
"default_value": 4
},
@@ -101,9 +68,6 @@
"skirt_gap": {
"default_value": 6
},
- "cool_fan_full_at_height": {
- "default_value": 0.4
- },
"support_enable": {
"default_value": false
}
diff --git a/resources/definitions/builder_premium_large.def.json b/resources/definitions/builder_premium_large.def.json
index 2e0cd4f839..d19382a591 100644
--- a/resources/definitions/builder_premium_large.def.json
+++ b/resources/definitions/builder_premium_large.def.json
@@ -35,8 +35,6 @@
"material_standby_temperature": { "value": "material_print_temperature" },
"switch_extruder_retraction_speeds": {"default_value": 15 },
- "switch_extruder_retraction_speed": {"default_value": 15 },
- "switch_extruder_prime_speed": {"default_value": 15 },
"switch_extruder_retraction_amount": {"value": 1 },
"speed_travel": { "value": "100" },
@@ -50,8 +48,8 @@
"speed_wall_0": { "value": "math.ceil(speed_wall * 20 / 25)" },
"speed_wall_x": { "value": "speed_wall" },
- "prime_tower_position_x": { "default_value": 175 },
- "prime_tower_position_y": { "default_value": 178 },
+ "prime_tower_position_x": { "value": "175" },
+ "prime_tower_position_y": { "value": "178" },
"prime_tower_wipe_enabled": { "default_value": false },
"prime_tower_min_volume": { "default_value": 50 },
@@ -85,15 +83,13 @@
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 15 },
- "retraction_retract_speed": { "default_value": 15 },
- "retraction_prime_speed": { "default_value": 15 },
"travel_retract_before_outer_wall": { "default_value": true },
"skin_overlap": { "value": "15" },
"adhesion_type": { "default_value": "skirt" },
"machine_nozzle_heat_up_speed": { "default_value": 2 },
"machine_nozzle_cool_down_speed": { "default_value": 2 },
- "machine_head_polygon": { "default_value": [[-75, -18],[-75, 35],[18, 35],[18, -18]] },
- "gantry_height": { "default_value": 55 },
+ "machine_head_with_fans_polygon": { "default_value": [[-75, -18],[-75, 35],[18, 35],[18, -18]] },
+ "gantry_height": { "value": "55" },
"machine_max_feedrate_x": { "default_value": 300 },
"machine_max_feedrate_y": { "default_value": 300 },
"machine_max_feedrate_z": { "default_value": 40 },
diff --git a/resources/definitions/builder_premium_medium.def.json b/resources/definitions/builder_premium_medium.def.json
index 58e7c18ed8..e5b8f1785c 100644
--- a/resources/definitions/builder_premium_medium.def.json
+++ b/resources/definitions/builder_premium_medium.def.json
@@ -35,8 +35,6 @@
"material_standby_temperature": { "value": "material_print_temperature" },
"switch_extruder_retraction_speeds": {"default_value": 15 },
- "switch_extruder_retraction_speed": {"default_value": 15 },
- "switch_extruder_prime_speed": {"default_value": 15 },
"switch_extruder_retraction_amount": {"value": 1 },
"speed_travel": { "value": "100" },
@@ -50,8 +48,8 @@
"speed_wall_0": { "value": "math.ceil(speed_wall * 20 / 25)" },
"speed_wall_x": { "value": "speed_wall" },
- "prime_tower_position_x": { "default_value": 175 },
- "prime_tower_position_y": { "default_value": 178 },
+ "prime_tower_position_x": { "value": "175" },
+ "prime_tower_position_y": { "value": "178" },
"prime_tower_wipe_enabled": { "default_value": false },
"prime_tower_min_volume": { "default_value": 50 },
@@ -85,15 +83,13 @@
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 15 },
- "retraction_retract_speed": { "default_value": 15 },
- "retraction_prime_speed": { "default_value": 15 },
"travel_retract_before_outer_wall": { "default_value": true },
"skin_overlap": { "value": "15" },
"adhesion_type": { "default_value": "skirt" },
"machine_nozzle_heat_up_speed": { "default_value": 2 },
"machine_nozzle_cool_down_speed": { "default_value": 2 },
- "machine_head_polygon": { "default_value": [[-75, -18],[-75, 35],[18, 35],[18, -18]] },
- "gantry_height": { "default_value": 55 },
+ "machine_head_with_fans_polygon": { "default_value": [[-75, -18],[-75, 35],[18, 35],[18, -18]] },
+ "gantry_height": { "value": "55" },
"machine_max_feedrate_x": { "default_value": 300 },
"machine_max_feedrate_y": { "default_value": 300 },
"machine_max_feedrate_z": { "default_value": 40 },
diff --git a/resources/definitions/builder_premium_small.def.json b/resources/definitions/builder_premium_small.def.json
index 89e172592c..4bcbd7d526 100644
--- a/resources/definitions/builder_premium_small.def.json
+++ b/resources/definitions/builder_premium_small.def.json
@@ -34,8 +34,6 @@
"material_standby_temperature": { "value": "material_print_temperature" },
"switch_extruder_retraction_speeds": {"default_value": 15 },
- "switch_extruder_retraction_speed": {"default_value": 15 },
- "switch_extruder_prime_speed": {"default_value": 15 },
"switch_extruder_retraction_amount": {"value": 1 },
"speed_travel": { "value": "100" },
@@ -49,8 +47,8 @@
"speed_wall_0": { "value": "math.ceil(speed_wall * 20 / 25)" },
"speed_wall_x": { "value": "speed_wall" },
- "prime_tower_position_x": { "default_value": 175 },
- "prime_tower_position_y": { "default_value": 178 },
+ "prime_tower_position_x": { "value": "175" },
+ "prime_tower_position_y": { "value": "178" },
"prime_tower_wipe_enabled": { "default_value": false },
"prime_tower_min_volume": { "default_value": 50 },
@@ -84,15 +82,13 @@
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 15 },
- "retraction_retract_speed": { "default_value": 15 },
- "retraction_prime_speed": { "default_value": 15 },
"travel_retract_before_outer_wall": { "default_value": true },
"skin_overlap": { "value": "15" },
"adhesion_type": { "default_value": "skirt" },
"machine_nozzle_heat_up_speed": { "default_value": 2 },
"machine_nozzle_cool_down_speed": { "default_value": 2 },
- "machine_head_polygon": { "default_value": [[-75, -18],[-75, 35],[18, 35],[18, -18]] },
- "gantry_height": { "default_value": 55 },
+ "machine_head_with_fans_polygon": { "default_value": [[-75, -18],[-75, 35],[18, 35],[18, -18]] },
+ "gantry_height": { "value": "55" },
"machine_max_feedrate_x": { "default_value": 300 },
"machine_max_feedrate_y": { "default_value": 300 },
"machine_max_feedrate_z": { "default_value": 40 },
diff --git a/resources/definitions/cartesio.def.json b/resources/definitions/cartesio.def.json
index 9c7a95cceb..e7a005682d 100644
--- a/resources/definitions/cartesio.def.json
+++ b/resources/definitions/cartesio.def.json
@@ -10,7 +10,6 @@
"has_machine_quality": true,
"has_materials": true,
- "has_machine_materials": true,
"has_variants": true,
"variants_name": "Tool",
@@ -35,7 +34,7 @@
"machine_extruder_count": { "default_value": 2 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
- "gantry_height": { "default_value": 35 },
+ "gantry_height": { "value": "35" },
"machine_height": { "default_value": 400 },
"machine_depth": { "default_value": 270 },
"machine_width": { "default_value": 430 },
@@ -45,8 +44,8 @@
"prime_tower_enable": { "default_value": false },
"prime_tower_min_volume": { "value": "0.7" },
"prime_tower_size": { "value": 24.0 },
- "prime_tower_position_x": { "value": 125 },
- "prime_tower_position_y": { "value": 70 },
+ "prime_tower_position_x": { "value": "125" },
+ "prime_tower_position_y": { "value": "70" },
"prime_blob_enable": { "default_value": false },
"machine_max_feedrate_z": { "default_value": 20 },
"machine_disallowed_areas": { "default_value": [
diff --git a/resources/definitions/cocoon_create_modelmaker.def.json b/resources/definitions/cocoon_create_modelmaker.def.json
index 22aa75d09e..b738dc64ff 100644
--- a/resources/definitions/cocoon_create_modelmaker.def.json
+++ b/resources/definitions/cocoon_create_modelmaker.def.json
@@ -39,7 +39,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 10
+ "value": "10"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -47,9 +47,6 @@
"material_diameter": {
"default_value": 1.75
},
- "material_print_temperature": {
- "default_value": 220
- },
"layer_height": {
"default_value": 0.10
},
@@ -65,21 +62,6 @@
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 70
- },
- "speed_layer_0": {
- "default_value": 20
- },
"support_enable": {
"default_value": true
},
diff --git a/resources/definitions/creality_base.def.json b/resources/definitions/creality_base.def.json
new file mode 100644
index 0000000000..7e91fb4989
--- /dev/null
+++ b/resources/definitions/creality_base.def.json
@@ -0,0 +1,267 @@
+{
+ "name": "Creawsome Base Printer",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": false,
+ "author": "trouch.com",
+ "manufacturer": "Creality3D",
+ "file_formats": "text/x-gcode",
+ "first_start_actions": ["MachineSettingsAction"],
+
+ "machine_extruder_trains": {
+ "0": "creality_base_extruder_0"
+ },
+
+ "has_materials": true,
+ "has_variants": true,
+ "has_machine_quality": true,
+ "variants_name": "Nozzle Size",
+
+ "preferred_variant_name": "0.4mm Nozzle",
+ "preferred_quality_type": "standard",
+ "preferred_material": "generic_pla",
+ "exclude_materials": [
+ "Vertex_Delta_ABS",
+ "Vertex_Delta_PET",
+ "Vertex_Delta_PLA",
+ "Vertex_Delta_TPU",
+ "chromatik_pla",
+ "dsm_arnitel2045_175",
+ "dsm_novamid1070_175",
+ "fabtotum_abs",
+ "fabtotum_nylon",
+ "fabtotum_pla",
+ "fabtotum_tpu",
+ "fiberlogy_hd_pla",
+ "filo3d_pla",
+ "filo3d_pla_green",
+ "filo3d_pla_red",
+ "generic_abs",
+ "generic_bam",
+ "generic_cffcpe",
+ "generic_cffpa",
+ "generic_cpe",
+ "generic_cpe_plus",
+ "generic_gffcpe",
+ "generic_gffpa",
+ "generic_hips",
+ "generic_nylon",
+ "generic_pc",
+ "generic_petg",
+ "generic_pla",
+ "generic_pp",
+ "generic_pva",
+ "generic_tough_pla",
+ "generic_tpu",
+ "imade3d_petg_green",
+ "imade3d_petg_pink",
+ "imade3d_pla_green",
+ "imade3d_pla_pink",
+ "innofill_innoflex60_175",
+ "octofiber_pla",
+ "polyflex_pla",
+ "polymax_pla",
+ "polyplus_pla",
+ "polywood_pla",
+ "structur3d_dap100silicone",
+ "tizyx_abs",
+ "tizyx_pla",
+ "tizyx_pla_bois",
+ "ultimaker_abs_black",
+ "ultimaker_abs_blue",
+ "ultimaker_abs_green",
+ "ultimaker_abs_grey",
+ "ultimaker_abs_orange",
+ "ultimaker_abs_pearl-gold",
+ "ultimaker_abs_red",
+ "ultimaker_abs_silver-metallic",
+ "ultimaker_abs_white",
+ "ultimaker_abs_yellow",
+ "ultimaker_bam",
+ "ultimaker_cpe_black",
+ "ultimaker_cpe_blue",
+ "ultimaker_cpe_dark-grey",
+ "ultimaker_cpe_green",
+ "ultimaker_cpe_light-grey",
+ "ultimaker_cpe_plus_black",
+ "ultimaker_cpe_plus_transparent",
+ "ultimaker_cpe_plus_white",
+ "ultimaker_cpe_red",
+ "ultimaker_cpe_transparent",
+ "ultimaker_cpe_white",
+ "ultimaker_cpe_yellow",
+ "ultimaker_nylon_black",
+ "ultimaker_nylon_transparent",
+ "ultimaker_pc_black",
+ "ultimaker_pc_transparent",
+ "ultimaker_pc_white",
+ "ultimaker_pla_black",
+ "ultimaker_pla_blue",
+ "ultimaker_pla_green",
+ "ultimaker_pla_magenta",
+ "ultimaker_pla_orange",
+ "ultimaker_pla_pearl-white",
+ "ultimaker_pla_red",
+ "ultimaker_pla_silver-metallic",
+ "ultimaker_pla_transparent",
+ "ultimaker_pla_white",
+ "ultimaker_pla_yellow",
+ "ultimaker_pp_transparent",
+ "ultimaker_pva",
+ "ultimaker_tough_pla_black",
+ "ultimaker_tough_pla_green",
+ "ultimaker_tough_pla_red",
+ "ultimaker_tough_pla_white",
+ "ultimaker_tpu_black",
+ "ultimaker_tpu_blue",
+ "ultimaker_tpu_red",
+ "ultimaker_tpu_white",
+ "verbatim_bvoh_175",
+ "zyyx_pro_flex",
+ "zyyx_pro_pla"
+ ]
+ },
+ "overrides": {
+ "machine_name": { "default_value": "Creawsome Base Printer" },
+ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n" },
+ "machine_end_gcode": { "default_value": "G91 ;Relative positioning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y{machine_depth} ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" },
+
+ "machine_max_feedrate_x": { "value": 500 },
+ "machine_max_feedrate_y": { "value": 500 },
+ "machine_max_feedrate_z": { "value": 10 },
+ "machine_max_feedrate_e": { "value": 50 },
+
+ "machine_max_acceleration_x": { "value": 500 },
+ "machine_max_acceleration_y": { "value": 500 },
+ "machine_max_acceleration_z": { "value": 100 },
+ "machine_max_acceleration_e": { "value": 5000 },
+ "machine_acceleration": { "value": 500 },
+
+ "machine_max_jerk_xy": { "value": 10 },
+ "machine_max_jerk_z": { "value": 0.4 },
+ "machine_max_jerk_e": { "value": 5 },
+
+ "machine_heated_bed": { "default_value": true },
+
+ "material_diameter": { "default_value": 1.75 },
+
+ "acceleration_print": { "value": 500 },
+ "acceleration_travel": { "value": 500 },
+ "acceleration_travel_layer_0": { "value": "acceleration_travel" },
+ "acceleration_roofing": { "enabled": "acceleration_enabled and roofing_layer_count > 0 and top_layers > 0" },
+
+ "jerk_print": { "value": 8 },
+ "jerk_travel": { "value": "jerk_print" },
+ "jerk_travel_layer_0": { "value": "jerk_travel" },
+
+ "acceleration_enabled": { "value": false },
+ "jerk_enabled": { "value": false },
+
+ "speed_print": { "value": 50.0 } ,
+ "speed_infill": { "value": "speed_print" },
+ "speed_wall": { "value": "speed_print / 2" },
+ "speed_wall_0": { "value": "speed_wall" },
+ "speed_wall_x": { "value": "speed_wall" },
+ "speed_topbottom": { "value": "speed_print / 2" },
+ "speed_roofing": { "value": "speed_topbottom" },
+ "speed_travel": { "value": "150.0 if speed_print < 60 else 250.0 if speed_print > 100 else speed_print * 2.5" },
+ "speed_layer_0": { "value": 20.0 },
+ "speed_print_layer_0": { "value": "speed_layer_0" },
+ "speed_travel_layer_0": { "value": "100 if speed_layer_0 < 20 else 150 if speed_layer_0 > 30 else speed_layer_0 * 5" },
+ "speed_prime_tower": { "value": "speed_topbottom" },
+ "speed_support": { "value": "speed_wall_0" },
+ "speed_support_interface": { "value": "speed_topbottom" },
+ "speed_z_hop": { "value": 5 },
+
+ "skirt_brim_speed": { "value": "speed_layer_0" },
+
+ "line_width": { "value": "machine_nozzle_size" },
+
+ "optimize_wall_printing_order": { "value": "True" },
+
+ "material_initial_print_temperature": { "value": "material_print_temperature" },
+ "material_final_print_temperature": { "value": "material_print_temperature" },
+ "material_flow": { "value": 100 },
+ "travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
+
+ "z_seam_type": { "value": "'back'" },
+ "z_seam_corner": { "value": "'z_seam_corner_weighted'" },
+
+ "infill_sparse_density": { "value": "20" },
+ "infill_pattern": { "value": "'lines' if infill_sparse_density > 50 else 'cubic'" },
+ "infill_before_walls": { "value": false },
+ "infill_overlap": { "value": 30.0 },
+ "skin_overlap": { "value": 10.0 },
+ "infill_wipe_dist": { "value": 0.0 },
+ "wall_0_wipe_dist": { "value": 0.0 },
+
+ "fill_perimeter_gaps": { "value": "'everywhere'" },
+ "fill_outline_gaps": { "value": false },
+ "filter_out_tiny_gaps": { "value": false },
+
+ "retraction_speed": {
+ "maximum_value_warning": "machine_max_feedrate_e if retraction_enable else float('inf')",
+ "maximum_value": 200
+ },
+ "retraction_retract_speed": {
+ "maximum_value_warning": "machine_max_feedrate_e if retraction_enable else float('inf')",
+ "maximum_value": 200
+ },
+ "retraction_prime_speed": {
+ "maximum_value_warning": "machine_max_feedrate_e if retraction_enable else float('inf')",
+ "maximum_value": 200
+ },
+
+ "retraction_hop_enabled": { "value": "False" },
+ "retraction_hop": { "value": 0.2 },
+ "retraction_combing": { "value": "'off' if retraction_hop_enabled else 'noskin'" },
+ "retraction_combing_max_distance": { "value": 30 },
+ "travel_avoid_other_parts": { "value": true },
+ "travel_avoid_supports": { "value": true },
+ "travel_retract_before_outer_wall": { "value": true },
+
+ "retraction_enable": { "value": true },
+ "retraction_count_max": { "value": 100 },
+ "retraction_extrusion_window": { "value": 10 },
+ "retraction_min_travel": { "value": 1.5 },
+
+ "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
+ "cool_fan_enabled": { "value": true },
+ "cool_min_layer_time": { "value": 10 },
+
+ "adhesion_type": { "value": "'skirt'" },
+ "brim_replaces_support": { "value": false },
+ "skirt_gap": { "value": 10.0 },
+ "skirt_line_count": { "value": 3 },
+
+ "adaptive_layer_height_variation": { "value": 0.04 },
+ "adaptive_layer_height_variation_step": { "value": 0.04 },
+
+ "meshfix_maximum_resolution": { "value": "0.05" },
+ "meshfix_maximum_travel_resolution": { "value": "meshfix_maximum_resolution" },
+
+ "support_angle": { "value": "math.floor(math.degrees(math.atan(line_width/2.0/layer_height)))" },
+ "support_pattern": { "value": "'zigzag'" },
+ "support_infill_rate": { "value": "0 if support_tree_enable else 20" },
+ "support_use_towers": { "value": false },
+ "support_xy_distance": { "value": "wall_line_width_0 * 2" },
+ "support_xy_distance_overhang": { "value": "wall_line_width_0" },
+ "support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height*2" },
+ "support_xy_overrides_z": { "value": "'xy_overrides_z'" },
+ "support_wall_count": { "value": 1 },
+ "support_brim_enable": { "value": true },
+ "support_brim_width": { "value": 4 },
+
+ "support_interface_enable": { "value": true },
+ "support_interface_height": { "value": "layer_height * 4" },
+ "support_interface_density": { "value": 33.333 },
+ "support_interface_pattern": { "value": "'grid'" },
+ "support_interface_skip_height": { "value": 0.2 },
+ "minimum_support_area": { "value": 5 },
+ "minimum_interface_area": { "value": 10 },
+ "top_bottom_thickness": {"value": "layer_height_0 + layer_height * 3" },
+ "wall_thickness": {"value": "line_width * 2" }
+
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr-x.def.json b/resources/definitions/creality_cr-x.def.json
index 94ac20cbb5..13409a7212 100644
--- a/resources/definitions/creality_cr-x.def.json
+++ b/resources/definitions/creality_cr-x.def.json
@@ -1,5 +1,4 @@
{
- "id": "CR-X",
"version": 2,
"name": "Creality CR-X",
"inherits": "fdmprinter",
@@ -30,9 +29,8 @@
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 70},
"adhesion_type": { "default_value": "skirt" },
- "gantry_height": { "default_value": 30 },
+ "gantry_height": { "value": "30" },
"speed_print": { "default_value": 60 },
- "speed_travel": { "default_value": 120 },
"machine_max_acceleration_x": { "default_value": 500 },
"machine_max_acceleration_y": { "default_value": 500 },
"machine_max_acceleration_z": { "default_value": 100 },
@@ -43,9 +41,7 @@
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": { "default_value": "G21 ;metric values\nG28 ;home all\nG90 ;absolute positioning\nM107 ;start with the fan off\nG1 F2400 Z15.0 ;raise the nozzle 15mm\nM109 S{material_print_temperature} ;Set Extruder Temperature and Wait\nM190 S{material_bed_temperature}; Wait for bed temperature to reach target temp\nT0 ;Switch to Extruder 1\nG1 F3000 X5 Y10 Z0.2 ;move to prime start position\nG92 E0 ;reset extrusion distance\nG1 F600 X160 E15 ;prime nozzle in a line\nG1 F5000 X180 ;quick wipe\nG92 E0 ;reset extrusion distance" },
"machine_end_gcode": { "default_value": "M104 S0 ;hotend off\nM140 S0 ;bed off\nG92 E0\nG1 F2000 E-100 ;retract filament 100mm\nG92 E0\nG1 F3000 X0 Y270 ;move bed for easy part removal\nM84 ;disable steppers" },
- "material_print_temperature": { "default_value": 200 },
"wall_thickness": { "default_value": 1 },
- "top_bottom_thickness": { "default_value": 1 },
- "bottom_thickness": { "default_value": 1 }
+ "top_bottom_thickness": { "default_value": 1 }
}
}
diff --git a/resources/definitions/creality_cr10.def.json b/resources/definitions/creality_cr10.def.json
index fb63867163..85e0f0a435 100644
--- a/resources/definitions/creality_cr10.def.json
+++ b/resources/definitions/creality_cr10.def.json
@@ -1,95 +1,25 @@
{
"name": "Creality CR-10",
"version": 2,
- "inherits": "fdmprinter",
- "metadata": {
- "visible": true,
- "author": "Michael Wildermuth",
- "manufacturer": "Creality3D",
- "file_formats": "text/x-gcode",
- "preferred_quality_type": "draft",
- "machine_extruder_trains":
- {
- "0": "creality_cr10_extruder_0"
- }
- },
+ "inherits": "creality_base",
"overrides": {
- "machine_width": {
- "default_value": 300
- },
- "machine_height": {
- "default_value": 400
- },
- "machine_depth": {
- "default_value": 300
- },
- "machine_head_polygon": {
- "default_value": [
- [-30, 34],
- [-30, -32],
- [30, -32],
- [30, 34]
+ "machine_name": { "default_value": "Creality CR-10" },
+ "machine_width": { "default_value": 300 },
+ "machine_depth": { "default_value": 300 },
+ "machine_height": { "default_value": 400 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
]
},
- "layer_height_0": {
- "default_value": 0.2
- },
- "top_bottom_thickness": {
- "default_value": 0.6
- },
- "top_bottom_pattern_0": {
- "default_value": "concentric"
- },
- "infill_pattern": {
- "value": "'triangles'"
- },
- "retraction_enable": {
- "default_value": true
- },
- "retraction_amount": {
- "default_value": 5
- },
- "retraction_speed": {
- "default_value": 40
- },
- "cool_min_layer_time": {
- "default_value": 10
- },
- "adhesion_type": {
- "default_value": "skirt"
- },
- "skirt_line_count": {
- "default_value": 4
- },
- "skirt_gap": {
- "default_value": 5
- },
- "machine_end_gcode": {
- "default_value": "G91\nG1 F1800 E-3\nG1 F3000 Z10\nG90\nG28 X0 Y0 ; home x and y axis\nM106 S0 ; turn off cooling fan\nM104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors"
- },
- "machine_heated_bed": {
- "default_value": true
- },
- "gantry_height": {
- "default_value": 30
- },
- "acceleration_enabled": {
- "default_value": true
- },
- "acceleration_print": {
- "default_value": 500
- },
- "acceleration_travel": {
- "default_value": 500
- },
- "jerk_enabled": {
- "default_value": true
- },
- "jerk_print": {
- "default_value": 20
- },
- "jerk_travel": {
- "default_value": 20
- }
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
}
}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr10max.def.json b/resources/definitions/creality_cr10max.def.json
new file mode 100644
index 0000000000..a7e40d5bfc
--- /dev/null
+++ b/resources/definitions/creality_cr10max.def.json
@@ -0,0 +1,26 @@
+{
+ "name": "Creality CR-10 Max",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-10 Max" },
+ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\nM420 S1 Z2 ;Enable ABL using saved Mesh and Fade Height\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n"},
+ "machine_width": { "default_value": 450 },
+ "machine_depth": { "default_value": 450 },
+ "machine_height": { "default_value": 470 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-44, 34],
+ [-44, -34],
+ [38, -34],
+ [38, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 30 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr10mini.def.json b/resources/definitions/creality_cr10mini.def.json
new file mode 100644
index 0000000000..621be5f0f3
--- /dev/null
+++ b/resources/definitions/creality_cr10mini.def.json
@@ -0,0 +1,25 @@
+{
+ "name": "Creality CR-10 Mini",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-10 Mini" },
+ "machine_width": { "default_value": 300 },
+ "machine_depth": { "default_value": 220 },
+ "machine_height": { "default_value": 300 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr10s.def.json b/resources/definitions/creality_cr10s.def.json
index c368269a46..9884b95cb4 100644
--- a/resources/definitions/creality_cr10s.def.json
+++ b/resources/definitions/creality_cr10s.def.json
@@ -1,5 +1,11 @@
{
"name": "Creality CR-10S",
"version": 2,
- "inherits": "creality_cr10"
+ "inherits": "creality_cr10",
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-10S" }
+ },
+ "metadata": {
+ "quality_definition": "creality_base"
+ }
}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr10s4.def.json b/resources/definitions/creality_cr10s4.def.json
index 7145083674..ccecd41a1d 100644
--- a/resources/definitions/creality_cr10s4.def.json
+++ b/resources/definitions/creality_cr10s4.def.json
@@ -1,26 +1,25 @@
{
- "name": "Creality CR-10 S4",
+ "name": "Creality CR-10S4",
"version": 2,
- "inherits": "creality_cr10",
- "metadata": {
- "visible": true,
- "author": "Michael Wildermuth",
- "manufacturer": "Creality3D",
- "file_formats": "text/x-gcode",
- "machine_extruder_trains":
- {
- "0": "creality_cr10s4_extruder_0"
- }
- },
+ "inherits": "creality_base",
"overrides": {
- "machine_width": {
- "default_value": 400
+ "machine_name": { "default_value": "Creality CR-10S4" },
+ "machine_width": { "default_value": 400 },
+ "machine_depth": { "default_value": 400 },
+ "machine_height": { "default_value": 400 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
},
- "machine_height": {
- "default_value": 400
- },
- "machine_depth": {
- "default_value": 400
- }
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
}
}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr10s5.def.json b/resources/definitions/creality_cr10s5.def.json
index b082894a16..105e1d0458 100644
--- a/resources/definitions/creality_cr10s5.def.json
+++ b/resources/definitions/creality_cr10s5.def.json
@@ -1,26 +1,25 @@
{
- "name": "Creality CR-10 S5",
+ "name": "Creality CR-10S5",
"version": 2,
- "inherits": "creality_cr10",
- "metadata": {
- "visible": true,
- "author": "Michael Wildermuth",
- "manufacturer": "Creality3D",
- "file_formats": "text/x-gcode",
- "machine_extruder_trains":
- {
- "0": "creality_cr10s5_extruder_0"
- }
- },
+ "inherits": "creality_base",
"overrides": {
- "machine_width": {
- "default_value": 500
+ "machine_name": { "default_value": "Creality CR-10S5" },
+ "machine_width": { "default_value": 500 },
+ "machine_depth": { "default_value": 500 },
+ "machine_height": { "default_value": 500 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
},
- "machine_height": {
- "default_value": 500
- },
- "machine_depth": {
- "default_value": 500
- }
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
}
}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr10spro.def.json b/resources/definitions/creality_cr10spro.def.json
new file mode 100644
index 0000000000..28c8dda0a5
--- /dev/null
+++ b/resources/definitions/creality_cr10spro.def.json
@@ -0,0 +1,24 @@
+{
+ "name": "Creality CR-10S Pro",
+ "version": 2,
+ "inherits": "creality_cr10",
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-10S Pro" },
+ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\nM420 S1 Z2 ;Enable ABL using saved Mesh and Fade Height\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n"},
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-44, 34],
+ [-44, -34],
+ [38, -34],
+ [38, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 30 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "platform": "creality_cr10spro.stl",
+ "platform_offset": [ -150, 0, 150]
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr20.def.json b/resources/definitions/creality_cr20.def.json
new file mode 100644
index 0000000000..b18c2709e6
--- /dev/null
+++ b/resources/definitions/creality_cr20.def.json
@@ -0,0 +1,25 @@
+{
+ "name": "Creality CR-20",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-20" },
+ "machine_width": { "default_value": 220 },
+ "machine_depth": { "default_value": 220 },
+ "machine_height": { "default_value": 250 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr20pro.def.json b/resources/definitions/creality_cr20pro.def.json
new file mode 100644
index 0000000000..4e676bcb74
--- /dev/null
+++ b/resources/definitions/creality_cr20pro.def.json
@@ -0,0 +1,13 @@
+{
+ "name": "Creality CR-20 Pro",
+ "version": 2,
+ "inherits": "creality_cr20",
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-20 Pro" },
+ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\nM420 S1 Z2 ;Enable ABL using saved Mesh and Fade Height\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n"}
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base"
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_ender2.def.json b/resources/definitions/creality_ender2.def.json
new file mode 100644
index 0000000000..2a5e14c828
--- /dev/null
+++ b/resources/definitions/creality_ender2.def.json
@@ -0,0 +1,26 @@
+{
+ "name": "Creality Ender-2",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality Ender-2" },
+ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y100.0 Z0.28 F1500.0 E8 ;Draw the first line\nG1 X10.4 Y100.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E15 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n"},
+ "machine_width": { "default_value": 150 },
+ "machine_depth": { "default_value": 150 },
+ "machine_height": { "default_value": 200 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_ender3.def.json b/resources/definitions/creality_ender3.def.json
old mode 100755
new mode 100644
index 08d8e92b72..37df844560
--- a/resources/definitions/creality_ender3.def.json
+++ b/resources/definitions/creality_ender3.def.json
@@ -1,96 +1,33 @@
{
"name": "Creality Ender-3",
"version": 2,
- "inherits": "fdmprinter",
+ "inherits": "creality_base",
"metadata": {
+ "quality_definition": "creality_base",
"visible": true,
- "author": "Sacha Telgenhof",
- "manufacturer": "Creality3D",
- "file_formats": "text/x-gcode",
- "platform": "creality_ender3_platform.stl",
- "preferred_quality_type": "draft",
- "machine_extruder_trains":
- {
- "0": "creality_ender3_extruder_0"
- }
+ "platform": "creality_ender3.stl"
},
"overrides": {
- "machine_name": {
- "default_value": "Creality Ender-3"
- },
- "machine_width": {
- "default_value": 235
- },
- "machine_height": {
- "default_value": 250
- },
- "machine_depth": {
- "default_value": 235
- },
- "machine_heated_bed": {
- "default_value": true
- },
- "gantry_height": {
- "default_value": 30
- },
- "machine_head_polygon": {
+ "machine_name": { "default_value": "Creality Ender-3" },
+ "machine_width": { "default_value": 235 },
+ "machine_depth": { "default_value": 235 },
+ "machine_height": { "default_value": 250 },
+ "machine_disallowed_areas": {
"default_value": [
- [-30, 34],
- [-30, -32],
- [30, -32],
- [30, 34]
+ [[-117.5, 117.5], [-117.5, 108], [117.5, 108], [117.5, 117.5]],
+ [[-117.5, -108], [-117.5, -117.5], [117.5, -117.5], [117.5, -108]]
+ ]},
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
]
},
- "material_diameter": {
- "default_value": 1.75
- },
- "acceleration_enabled": {
- "default_value": true
- },
- "acceleration_print": {
- "default_value": 500
- },
- "acceleration_travel": {
- "default_value": 500
- },
- "jerk_enabled": {
- "default_value": true
- },
- "jerk_travel": {
- "default_value": 20
- },
- "layer_height": {
- "default_value": 0.10
- },
- "layer_height_0": {
- "default_value": 0.2
- },
- "adhesion_type": {
- "default_value": "skirt"
- },
- "top_bottom_thickness": {
- "default_value": 0.6
- },
- "retraction_amount": {
- "default_value": 5
- },
- "retraction_speed": {
- "default_value": 40
- },
- "cool_min_layer_time": {
- "default_value": 10
- },
- "skirt_line_count": {
- "default_value": 4
- },
- "skirt_gap": {
- "default_value": 5
- },
"machine_start_gcode": {
- "default_value": "; Ender 3 Custom Start G-code\nG28 ; Home all axes\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z0.3 F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z0.3 F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3 F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\n; End of custom start GCode"
+ "default_value": "; Ender 3 Custom Start G-code\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z0.3 F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z0.3 F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3 F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F5000.0 ; Move over to prevent blob squish"
},
- "machine_end_gcode": {
- "default_value": "; Ender 3 Custom End G-code\nG4 ; Wait\nM220 S100 ; Reset Speed factor override percentage to default (100%)\nM221 S100 ; Reset Extrude factor override percentage to default (100%)\nG91 ; Set coordinates to relative\nG1 F1800 E-3 ; Retract filament 3 mm to prevent oozing\nG1 F3000 Z20 ; Move Z Axis up 20 mm to allow filament ooze freely\nG90 ; Set coordinates to absolute\nG1 X0 Y{machine_depth} F1000 ; Move Heat Bed to the front for easy print removal\nM84 ; Disable stepper motors\n; End of custom end GCode"
- }
+
+ "gantry_height": { "value": 25 }
}
}
diff --git a/resources/definitions/creality_ender4.def.json b/resources/definitions/creality_ender4.def.json
new file mode 100644
index 0000000000..9c13797c92
--- /dev/null
+++ b/resources/definitions/creality_ender4.def.json
@@ -0,0 +1,27 @@
+{
+ "name": "Creality Ender-4",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality Ender-4" },
+ "machine_width": { "default_value": 452 },
+ "machine_depth": { "default_value": 468 },
+ "machine_height": { "default_value": 482 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 25 },
+
+ "speed_print": { "value": 80.0 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_ender5.def.json b/resources/definitions/creality_ender5.def.json
new file mode 100644
index 0000000000..1b4be4d71f
--- /dev/null
+++ b/resources/definitions/creality_ender5.def.json
@@ -0,0 +1,28 @@
+{
+ "name": "Creality Ender-5",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality Ender-5" },
+ "machine_end_gcode": { "default_value": "G91 ;Relative positioning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y0 ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" },
+ "machine_width": { "default_value": 220 },
+ "machine_depth": { "default_value": 220 },
+ "machine_height": { "default_value": 300 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 25 },
+
+ "speed_print": { "value": 80.0 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_ender5plus.def.json b/resources/definitions/creality_ender5plus.def.json
new file mode 100644
index 0000000000..48ebad61ea
--- /dev/null
+++ b/resources/definitions/creality_ender5plus.def.json
@@ -0,0 +1,28 @@
+{
+ "name": "Creality Ender-5 Plus",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality Ender-5 Plus" },
+ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\nM420 S1 Z2 ;Enable ABL using saved Mesh and Fade Height\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n"},
+ "machine_width": { "default_value": 350 },
+ "machine_depth": { "default_value": 350 },
+ "machine_height": { "default_value": 400 },
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
+ },
+
+ "gantry_height": { "value": 25 },
+
+ "speed_print": { "value": 80.0 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creatable_d3.def.json b/resources/definitions/creatable_d3.def.json
index 3fb1205ead..f621bcbe97 100644
--- a/resources/definitions/creatable_d3.def.json
+++ b/resources/definitions/creatable_d3.def.json
@@ -24,17 +24,15 @@
"machine_depth": { "default_value": 250 },
"machine_heated_bed": { "default_value": true },
"machine_shape": { "default_value": "elliptic" },
- "machine_max_feedrate_z": { "default_value": 300 },
- "gantry_height": {"default_value": 43},
+ "machine_max_feedrate_z": { "default_value": 300 },
+ "gantry_height": {"value": "43"},
"layer_height": { "default_value": 0.1 },
- "relative_extrusion": { "default_value": false },
+ "relative_extrusion": { "value": "False" },
"retraction_combing": { "default_value": "off" },
- "retraction_hop_enabled": { "default_value": true },
+ "retraction_hop_enabled": { "default_value": true },
"retraction_hop_only_when_collides": { "default_value": false },
- "retraction_retract_speed": { "default_value": 100 },
"retraction_speed": { "default_value": 100 },
"retraction_amount": { "default_value": 4.5 },
- "retraction_prime_speed": { "default_value": 45 },
"machine_start_gcode": {
"default_value": "G21\nG90\nM82\nM106 S255\nG28\nG92 E0\nG1 Z100 F5000\nM190 S50\nM109 S200\nG1 X-135\nG1 Z0.3\nG92 E-32\nG1 E0 F1000\nG1 E50 F200\nG1 F1000\nG1 X-125\nG92 E0"
},
diff --git a/resources/definitions/cubicon_3dp_110f.def.json b/resources/definitions/cubicon_3dp_110f.def.json
index 168b57cd66..eecfdd5911 100644
--- a/resources/definitions/cubicon_3dp_110f.def.json
+++ b/resources/definitions/cubicon_3dp_110f.def.json
@@ -1,5 +1,4 @@
{
- "id": "3DP-110F",
"version": 2,
"name": "Cubicon Single",
"inherits": "cubicon_common",
diff --git a/resources/definitions/cubicon_3dp_210f.def.json b/resources/definitions/cubicon_3dp_210f.def.json
index cc99899f92..5d8ff78487 100644
--- a/resources/definitions/cubicon_3dp_210f.def.json
+++ b/resources/definitions/cubicon_3dp_210f.def.json
@@ -1,5 +1,4 @@
{
- "id": "3DP-210F",
"version": 2,
"name": "Cubicon Style",
"inherits": "cubicon_common",
diff --git a/resources/definitions/cubicon_3dp_310f.def.json b/resources/definitions/cubicon_3dp_310f.def.json
index 90d0e3f25c..1dc78f0ebf 100644
--- a/resources/definitions/cubicon_3dp_310f.def.json
+++ b/resources/definitions/cubicon_3dp_310f.def.json
@@ -1,5 +1,4 @@
{
- "id": "3DP-310F",
"version": 2,
"name": "Cubicon Single Plus",
"inherits": "cubicon_common",
diff --git a/resources/definitions/cubicon_common.def.json b/resources/definitions/cubicon_common.def.json
index ae085c7552..6b1e3d953e 100644
--- a/resources/definitions/cubicon_common.def.json
+++ b/resources/definitions/cubicon_common.def.json
@@ -23,77 +23,34 @@
"travel_compensate_overlapping_walls_enabled": {
"default_value": false
},
- "travel_compensate_overlapping_walls_0_enabled": {
- "default_value": false
- },
- "travel_compensate_overlapping_walls_x_enabled": {
- "default_value": false
- },
"layer_height": {
"default_value": 0.2
},
"layer_height_0": {
"default_value": 0.2
},
- "infill_line_width": {
- "default_value": 0.6
- },
"adhesion_type": {
"default_value": "raft"
},
- "roofing_pattern": { "default_value": "lines" },
"top_bottom_pattern": { "default_value": "lines" },
- "top_bottom_pattern_0": {
- "default_value": "zigzag"
- },
"fill_perimeter_gaps": { "default_value": "everywhere" },
- "infill_pattern": {
- "default_value": "zigzag"
- },
"infill_sparse_density": { "default_value": 20 },
- "infill_overlap": {
- "default_value": 15
- },
"infill_before_walls": { "default_value": false },
- "infill_sparse_thickness": { "default_value": 0.2 },
"top_bottom_thickness": {
"default_value": 1.0
},
- "top_thickness": {
- "default_value": 1.0
- },
"bottom_thickness": {
- "default_value": 0.6,
"value": "top_bottom_thickness * 0.6"
},
- "roofing_layer_count": {
- "default_value": 1
- },
- "skin_preshrink": { "default_value": true },
"material_flow_layer_0": { "default_value": 100 },
- "top_skin_preshrink": { "default_value": 1.2 },
- "bottom_skin_preshrink": { "default_value": 1.2 },
"max_skin_angle_for_expansion": { "default_value": 90 },
- "min_skin_width_for_expansion": { "default_value": 2.7475 },
"skin_angles": { "default_value": "[135,45]" },
- "roofing_angles": { "default_value": "[135,45]" },
"coasting_volume": { "default_value": 0.032 },
"wall_thickness": { "default_value": 1.2 },
- "wall_line_count": { "default_value": 3 },
- "speed_wall_0": { "default_value": 25 },
- "skin_overlap": { "default_value": 5 },
"cool_min_layer_time_fan_speed_max": { "default_value": 15 },
"cool_min_layer_time": { "default_value": 15 },
- "support_roof_pattern": { "default_value": "zigzag" },
- "support_bottom_pattern": { "default_value": "zigzag" },
"support_interface_pattern": { "default_value": "zigzag" },
"support_pattern": { "default_value": "zigzag" },
- "retraction_amount": { "default_value": 1.5 },
- "top_layers": {
- "default_value": 5
- },
- "bottom_layers": {
- "default_value": 3
- }
+ "retraction_amount": { "default_value": 1.5 }
}
}
\ No newline at end of file
diff --git a/resources/definitions/cubicon_dual_pro_a30.def.json b/resources/definitions/cubicon_dual_pro_a30.def.json
new file mode 100644
index 0000000000..6431c917a5
--- /dev/null
+++ b/resources/definitions/cubicon_dual_pro_a30.def.json
@@ -0,0 +1,44 @@
+{
+ "version": 2,
+ "name": "Cubicon Dual Pro-A30",
+ "inherits": "cubicon_common",
+ "metadata": {
+ "author": "Cubicon R&D Center",
+ "manufacturer": "Cubicon",
+ "visible": true,
+ "file_formats": "text/x-gcode",
+ "supports_usb_connection": false,
+ "machine_extruder_trains": {
+ "0": "cubicon_dual_pro_a30_extruder_0",
+ "1": "cubicon_dual_pro_a30_extruder_1"
+ },
+ "platform_offset": [
+ 0,
+ 0,
+ 0
+ ]
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Cubicon Dual Pro-A30"
+ },
+ "machine_start_gcode": {
+ "default_value": "M911 Dual Pro-A30C\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\nG1 Z15.0 F6000 ;move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0"
+ },
+ "machine_width": {
+ "default_value": 300
+ },
+ "machine_depth": {
+ "default_value": 300
+ },
+ "machine_height": {
+ "default_value": 300
+ },
+ "material_bed_temp_wait":{
+ "default_value": false
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ }
+ }
+}
diff --git a/resources/definitions/cubicon_style_plus_a15.def.json b/resources/definitions/cubicon_style_plus_a15.def.json
new file mode 100644
index 0000000000..a55d5aa791
--- /dev/null
+++ b/resources/definitions/cubicon_style_plus_a15.def.json
@@ -0,0 +1,40 @@
+{
+ "version": 2,
+ "name": "Cubicon Style Plus-A15",
+ "inherits": "cubicon_common",
+ "metadata": {
+ "author": "Cubicon R&D Center",
+ "manufacturer": "Cubicon",
+ "visible": true,
+ "file_formats": "text/x-gcode",
+ "supports_usb_connection": false,
+ "machine_extruder_trains": {
+ "0": "cubicon_style_plus_a15_extruder_0"
+ },
+ "platform_offset": [
+ 0,
+ 0,
+ 0
+ ]
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Cubicon Style Plus-A15"
+ },
+ "machine_start_gcode": {
+ "default_value": "M911 Style Plus-A15\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\nG1 Z15.0 F6000 ;move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0"
+ },
+ "machine_width": {
+ "default_value": 150
+ },
+ "machine_depth": {
+ "default_value": 150
+ },
+ "machine_height": {
+ "default_value": 150
+ },
+ "material_bed_temp_wait":{
+ "default_value": false
+ }
+ }
+}
diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json
index 89d94ff6b7..30c0abdab2 100644
--- a/resources/definitions/dagoma_discoeasy200.def.json
+++ b/resources/definitions/dagoma_discoeasy200.def.json
@@ -38,7 +38,7 @@
]
},
"gantry_height": {
- "default_value": 10
+ "value": "10"
},
"machine_start_gcode": {
"default_value": ";Gcode by Cura\nG90\nM106 S255\nG28 X Y\nG1 X50\nM109 R90\nG28\nM104 S{material_print_temperature_layer_0}\nG29\nM107\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E10\nG92 E0\nG1 Z3\nG1 F6000\n"
@@ -52,9 +52,6 @@
"speed_print": {
"default_value": 60
},
- "speed_travel": {
- "default_value": 100
- },
"retraction_amount": {
"default_value": 3.5
},
diff --git a/resources/definitions/dagoma_magis.def.json b/resources/definitions/dagoma_magis.def.json
index 75e6e449cd..dc5a0f86d2 100644
--- a/resources/definitions/dagoma_magis.def.json
+++ b/resources/definitions/dagoma_magis.def.json
@@ -38,7 +38,7 @@
]
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_shape": {
"default_value": "elliptic"
@@ -55,9 +55,6 @@
"speed_print": {
"default_value": 40
},
- "speed_travel": {
- "default_value": 120
- },
"retraction_amount": {
"default_value": 3.8
},
diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json
index 67c8795678..43a3e0c4f1 100644
--- a/resources/definitions/dagoma_neva.def.json
+++ b/resources/definitions/dagoma_neva.def.json
@@ -38,7 +38,7 @@
]
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_shape": {
"default_value": "elliptic"
@@ -55,9 +55,6 @@
"speed_print": {
"default_value": 40
},
- "speed_travel": {
- "default_value": 120
- },
"retraction_amount": {
"default_value": 3.8
},
diff --git a/resources/definitions/delta_go.def.json b/resources/definitions/delta_go.def.json
index cd1fb180c2..04f0580898 100644
--- a/resources/definitions/delta_go.def.json
+++ b/resources/definitions/delta_go.def.json
@@ -16,12 +16,8 @@
"overrides": {
"machine_name": { "default_value": "Delta Go" },
"default_material_print_temperature": { "default_value": 210 },
- "speed_travel": { "default_value": 150 },
"prime_tower_size": { "default_value": 8.66 },
"infill_sparse_density": { "default_value": 10 },
- "speed_wall_x": { "default_value": 30 },
- "speed_wall_0": { "default_value": 30 },
- "speed_topbottom": { "default_value": 20 },
"layer_height": { "default_value": 0.15 },
"speed_print": { "default_value": 30 },
"machine_heated_bed": { "default_value": false },
diff --git a/resources/definitions/deltabot.def.json b/resources/definitions/deltabot.def.json
index 95435f659d..ad6a207bb2 100644
--- a/resources/definitions/deltabot.def.json
+++ b/resources/definitions/deltabot.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Ultimaker",
- "manufacturer": "Danny Lu",
+ "manufacturer": "Custom",
"file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0],
"machine_extruder_trains":
@@ -15,15 +15,10 @@
},
"overrides": {
- "speed_travel": { "default_value": 150 },
"prime_tower_size": { "default_value": 8.660254037844387 },
"infill_sparse_density": { "default_value": 10 },
- "speed_wall_x": { "default_value": 30 },
- "speed_wall_0": { "default_value": 30 },
- "speed_topbottom": { "default_value": 30 },
"layer_height": { "default_value": 0.2 },
"speed_print": { "default_value": 30 },
- "speed_infill": { "default_value": 30 },
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": true },
diff --git a/resources/definitions/deltacomb.def.json b/resources/definitions/deltacomb.def.json
index 026dfca9ed..ac2ea5abe1 100755
--- a/resources/definitions/deltacomb.def.json
+++ b/resources/definitions/deltacomb.def.json
@@ -13,7 +13,6 @@
"platform": "deltacomb.stl",
"has_machine_quality": true,
"has_materials": true,
- "has_machine_materials": false,
"has_variants": true,
"variants_name": "Head",
"preferred_variant_name": "E3D 0.40mm",
@@ -38,7 +37,7 @@
"retraction_amount" : { "default_value": 3.5 },
"retraction_speed" : { "default_value": 30 },
"retraction_combing" : { "default_value": "noskin" },
- "travel_avoid_distance": { "default_value": 1, "value": "1" },
+ "travel_avoid_distance": { "value": "1" },
"speed_print" : { "default_value": 80 },
"speed_infill": { "value": "round(speed_print * 1.05, 0)" },
"speed_topbottom": { "value": "round(speed_print * 0.95, 0)" },
@@ -46,7 +45,7 @@
"speed_wall_0": { "value": "30" },
"speed_wall_x": { "value": "speed_wall" },
"speed_layer_0": { "value": "min(round(speed_print * 0.75, 0), 45.0)" },
- "speed_travel": { "default_value": 150, "value": 150 },
+ "speed_travel": { "value": 150 },
"speed_travel_layer_0": { "value": "round(speed_travel * 0.7, 0)" },
"skirt_brim_speed": { "value": "speed_layer_0" },
"skirt_line_count": { "default_value": 3 },
@@ -58,10 +57,10 @@
"support_z_distance": { "value": "layer_height * 2" },
"support_bottom_distance": { "value": "layer_height" },
"support_use_towers" : { "default_value": false },
- "jerk_enabled": { "default_value": 1, "value": "1" },
- "jerk_infill" : { "default_value": 5, "value": "5" },
- "jerk_support" : { "default_value": 5, "value": "5" },
- "acceleration_enabled": { "default_value": 1, "value": "1" },
+ "jerk_enabled": { "value": "True" },
+ "jerk_infill" : { "value": "5" },
+ "jerk_support" : { "value": "5" },
+ "acceleration_enabled": { "value": "1" },
"acceleration_travel" : { "value": 5000 },
"machine_max_feedrate_z" : { "default_value": 300 }
}
diff --git a/resources/definitions/easyarts_ares.def.json b/resources/definitions/easyarts_ares.def.json
index 5655d0a795..18d73a3531 100644
--- a/resources/definitions/easyarts_ares.def.json
+++ b/resources/definitions/easyarts_ares.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "nliaudat",
- "manufacturer": "EasyArts (discontinued)",
+ "manufacturer": "EasyArts",
"file_formats": "text/x-gcode",
"machine_extruder_trains":
{
@@ -49,27 +49,9 @@
"top_bottom_thickness": {
"default_value": 1
},
- "bottom_thickness": {
- "default_value": 1
- },
"speed_print": {
"default_value": 75
},
- "speed_infill": {
- "default_value": 100
- },
- "speed_wall": {
- "default_value": 25
- },
- "speed_topbottom": {
- "default_value": 15
- },
- "speed_travel": {
- "default_value": 150
- },
- "speed_layer_0": {
- "default_value": 30
- },
"support_enable": {
"default_value": true
}
diff --git a/resources/definitions/erzay3d.def.json b/resources/definitions/erzay3d.def.json
new file mode 100644
index 0000000000..875aea708e
--- /dev/null
+++ b/resources/definitions/erzay3d.def.json
@@ -0,0 +1,81 @@
+{
+ "name": "Erzay3D",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Alexander Kirsanov",
+ "manufacturer": "Robokinetika",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "machine_extruder_trains":
+ {
+ "0": "erzay3d_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_start_gcode" : { "default_value": "G28\nG1 Z15.0 F6000\nG92 E0" },
+ "machine_shape": { "default_value": "elliptic"},
+ "machine_name": { "default_value": "Erzay3D" },
+ "machine_depth": { "default_value": 210 },
+ "machine_width": { "default_value": 210 },
+ "machine_height": { "default_value": 230 },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_center_is_zero": { "default_value": true },
+ "machine_extruder_count": { "default_value": 1 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_heated_bed": { "default_value": true },
+ "material_bed_temp_wait": { "default_value": true },
+ "material_print_temp_wait": { "default_value": true },
+ "material_print_temp_prepend": { "default_value": true },
+ "machine_buildplate_type": { "default_value": "glass" },
+ "machine_nozzle_head_distance": { "default_value": 2.5 },
+ "machine_heat_zone_length": { "default_value": 12.5 },
+ "machine_max_feedrate_x": { "default_value": 200 },
+ "machine_max_feedrate_y": { "default_value": 200 },
+ "machine_max_feedrate_z": { "default_value": 200 },
+ "machine_max_feedrate_e": { "default_value": 50 },
+ "machine_max_acceleration_x": { "default_value": 3000 },
+ "machine_max_acceleration_y": { "default_value": 3000 },
+ "machine_max_acceleration_z": { "default_value": 3000 },
+ "machine_max_acceleration_e": { "default_value": 3000 },
+ "machine_acceleration": { "default_value": 1000 },
+ "machine_max_jerk_xy": { "default_value": 10 },
+ "machine_max_jerk_z": { "default_value": 10 },
+ "machine_max_jerk_e": { "default_value": 10 },
+ "machine_steps_per_mm_x": { "default_value": 1600 },
+ "machine_steps_per_mm_y": { "default_value": 1600 },
+ "machine_steps_per_mm_z": { "default_value": 1600 },
+ "machine_steps_per_mm_e": { "default_value": 174 },
+ "machine_feeder_wheel_diameter": { "default_value": 12 },
+
+ "layer_height": { "default_value": 0.2 },
+ "layer_height_0": { "default_value": 0.2 },
+
+ "ironing_pattern": { "default_value": "concentric" },
+ "ironing_flow": { "default_value": 7.0 },
+
+ "infill_sparse_density": { "default_value": 20 },
+
+ "default_material_print_temperature": { "default_value": 220 },
+ "retraction_amount": { "default_value": 6.5 },
+
+ "speed_print": { "default_value": 40 },
+ "speed_equalize_flow_enabled": { "default_value": true },
+ "speed_equalize_flow_max": { "default_value": 100 },
+
+ "acceleration_print": { "default_value": 1000 },
+
+ "jerk_print": { "default_value": 10 },
+
+ "support_angle": { "default_value": 65 },
+ "support_brim_enable": { "default_value": true },
+
+ "adhesion_type": { "default_value": "skirt" },
+ "brim_outside_only": { "default_value": false },
+
+ "meshfix_maximum_resolution": { "default_value": 0.05 }
+ }
+}
diff --git a/resources/definitions/fabtotum.def.json b/resources/definitions/fabtotum.def.json
index 10c8f68844..355f6a1434 100644
--- a/resources/definitions/fabtotum.def.json
+++ b/resources/definitions/fabtotum.def.json
@@ -28,7 +28,7 @@
"machine_end_gcode": {
"default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-3 X+5 Y+5 F5000 ;move Z up a bit and retract filament even more\n;end of the print\nM84 ;steppers off\nG90 ;absolute positioning\nM300 S2 ;FAB bep bep (end print)"
},
- "gantry_height": { "default_value": 55 },
+ "gantry_height": { "value": "55" },
"machine_width": { "default_value": 214 },
"machine_height": { "default_value": 241.5 },
"machine_depth": { "default_value": 234 },
@@ -50,8 +50,8 @@
"retraction_hop_enabled": { "default_value": false },
"material_final_print_temperature": { "value": "material_print_temperature - 5" },
"material_initial_print_temperature": { "value": "material_print_temperature" },
- "travel_avoid_distance": { "default_value": 1, "value": 1 },
- "speed_travel": { "default_value": 200, "value": 200 },
+ "travel_avoid_distance": { "value": 1 },
+ "speed_travel": { "value": 200 },
"speed_infill": { "value": "round(speed_print * 1.05, 0)" },
"speed_topbottom": { "value": "round(speed_print * 0.95, 0)" },
"speed_wall": { "value": "speed_print" },
diff --git a/resources/definitions/fdmextruder.def.json b/resources/definitions/fdmextruder.def.json
index 0af1e68075..9d1e3c305e 100644
--- a/resources/definitions/fdmextruder.def.json
+++ b/resources/definitions/fdmextruder.def.json
@@ -6,7 +6,7 @@
"type": "extruder",
"author": "Ultimaker",
"manufacturer": "Unknown",
- "setting_version": 1,
+ "setting_version": 11,
"visible": false,
"position": "0"
},
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 278171827d..b607c24d70 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -7,17 +7,20 @@
"author": "Ultimaker",
"category": "Other",
"manufacturer": "Unknown",
- "setting_version": 1,
+ "setting_version": 11,
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g",
"visible": false,
"has_materials": true,
+ "has_variants": false,
+ "has_machine_quality": false,
"preferred_material": "generic_pla",
"preferred_quality_type": "normal",
"machine_extruder_trains":
{
"0": "fdmextruder"
},
- "supports_usb_connection": true
+ "supports_usb_connection": true,
+ "supports_network_connection": false
},
"settings":
{
@@ -203,6 +206,16 @@
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
+ "machine_heated_build_volume":
+ {
+ "label": "Has Build Volume Temperature Stabilization",
+ "description": "Whether the machine is able to stabilize the build volume temperature.",
+ "default_value": false,
+ "type": "bool",
+ "settable_per_mesh": false,
+ "settable_per_extruder": false,
+ "settable_per_meshgroup": false
+ },
"machine_center_is_zero":
{
"label": "Is Center Origin",
@@ -227,7 +240,7 @@
},
"extruders_enabled_count":
{
- "label": "Number of Extruders that are enabled",
+ "label": "Number of Extruders That Are Enabled",
"description": "Number of extruder trains that are enabled; automatically set in software",
"value": "machine_extruder_count",
"default_value": 1,
@@ -240,7 +253,7 @@
},
"machine_nozzle_tip_outer_diameter":
{
- "label": "Outer nozzle diameter",
+ "label": "Outer Nozzle Diameter",
"description": "The outer diameter of the tip of the nozzle.",
"unit": "mm",
"default_value": 1,
@@ -252,7 +265,7 @@
},
"machine_nozzle_head_distance":
{
- "label": "Nozzle length",
+ "label": "Nozzle Length",
"description": "The height difference between the tip of the nozzle and the lowest part of the print head.",
"unit": "mm",
"default_value": 3,
@@ -263,7 +276,7 @@
},
"machine_nozzle_expansion_angle":
{
- "label": "Nozzle angle",
+ "label": "Nozzle Angle",
"description": "The angle between the horizontal plane and the conical part right above the tip of the nozzle.",
"unit": "°",
"type": "int",
@@ -276,7 +289,7 @@
},
"machine_heat_zone_length":
{
- "label": "Heat zone length",
+ "label": "Heat Zone Length",
"description": "The distance from the tip of the nozzle in which heat from the nozzle is transferred to the filament.",
"unit": "mm",
"default_value": 16,
@@ -310,7 +323,7 @@
},
"machine_nozzle_heat_up_speed":
{
- "label": "Heat up speed",
+ "label": "Heat Up Speed",
"description": "The speed (°C/s) by which the nozzle heats up averaged over the window of normal printing temperatures and the standby temperature.",
"default_value": 2.0,
"unit": "°C/s",
@@ -321,7 +334,7 @@
},
"machine_nozzle_cool_down_speed":
{
- "label": "Cool down speed",
+ "label": "Cool Down Speed",
"description": "The speed (°C/s) by which the nozzle cools down averaged over the window of normal printing temperatures and the standby temperature.",
"default_value": 2.0,
"unit": "°C/s",
@@ -343,7 +356,7 @@
},
"machine_gcode_flavor":
{
- "label": "G-code flavour",
+ "label": "G-code Flavor",
"description": "The type of g-code to be generated.",
"type": "enum",
"options":
@@ -374,9 +387,19 @@
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
+ "machine_extruders_share_heater":
+ {
+ "label": "Extruders Share Heater",
+ "description": "Whether the extruders share a single heater rather than each extruder having its own heater.",
+ "type": "bool",
+ "default_value": false,
+ "settable_per_mesh": false,
+ "settable_per_extruder": false,
+ "settable_per_meshgroup": false
+ },
"machine_disallowed_areas":
{
- "label": "Disallowed areas",
+ "label": "Disallowed Areas",
"description": "A list of polygons with areas the print head is not allowed to enter.",
"type": "polygons",
"default_value":
@@ -398,37 +421,9 @@
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
- "machine_head_polygon":
- {
- "label": "Machine head polygon",
- "description": "A 2D silhouette of the print head (fan caps excluded).",
- "type": "polygon",
- "default_value":
- [
- [
- -1,
- 1
- ],
- [
- -1,
- -1
- ],
- [
- 1,
- -1
- ],
- [
- 1,
- 1
- ]
- ],
- "settable_per_mesh": false,
- "settable_per_extruder": false,
- "settable_per_meshgroup": false
- },
"machine_head_with_fans_polygon":
{
- "label": "Machine head & Fan polygon",
+ "label": "Machine Head & Fan Polygon",
"description": "A 2D silhouette of the print head (fan caps included).",
"type": "polygon",
"default_value":
@@ -456,9 +451,10 @@
},
"gantry_height":
{
- "label": "Gantry height",
+ "label": "Gantry Height",
"description": "The height difference between the tip of the nozzle and the gantry system (X and Y axes).",
"default_value": 99999999999,
+ "value": "machine_height",
"type": "float",
"settable_per_mesh": false,
"settable_per_extruder": false,
@@ -487,7 +483,7 @@
},
"machine_use_extruder_offset_to_offset_coords":
{
- "label": "Offset With Extruder",
+ "label": "Offset with Extruder",
"description": "Apply the extruder offset to the coordinate system.",
"type": "bool",
"default_value": true,
@@ -522,7 +518,7 @@
"description": "The maximum speed for the motor of the X-direction.",
"unit": "mm/s",
"type": "float",
- "default_value": 500,
+ "default_value": 299792458000,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -533,7 +529,7 @@
"description": "The maximum speed for the motor of the Y-direction.",
"unit": "mm/s",
"type": "float",
- "default_value": 500,
+ "default_value": 299792458000,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -544,7 +540,7 @@
"description": "The maximum speed for the motor of the Z-direction.",
"unit": "mm/s",
"type": "float",
- "default_value": 5,
+ "default_value": 299792458000,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -890,7 +886,7 @@
"maximum_value_warning": "3 * machine_nozzle_size",
"default_value": 0.4,
"type": "float",
- "enabled": "support_enable",
+ "enabled": "(support_enable or support_tree_enable)",
"value": "line_width",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
@@ -906,7 +902,7 @@
"minimum_value_warning": "0.1 + 0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
- "enabled": "support_enable and support_interface_enable",
+ "enabled": "(support_enable or support_tree_enable) and support_interface_enable",
"limit_to_extruder": "support_interface_extruder_nr",
"value": "line_width",
"settable_per_mesh": false,
@@ -923,7 +919,7 @@
"minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
- "enabled": "support_enable and support_roof_enable",
+ "enabled": "(support_enable or support_tree_enable) and support_roof_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_line_width')",
"settable_per_mesh": false,
@@ -939,7 +935,7 @@
"minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
- "enabled": "support_enable and support_bottom_enable",
+ "enabled": "(support_enable or support_tree_enable) and support_bottom_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_line_width')",
"settable_per_mesh": false,
@@ -961,20 +957,20 @@
"maximum_value_warning": "2 * machine_nozzle_size",
"settable_per_mesh": false,
"settable_per_extruder": true
- },
- "initial_layer_line_width_factor":
- {
- "label": "Initial Layer Line Width",
- "description": "Multiplier of the line width on the first layer. Increasing this could improve bed adhesion.",
- "type": "float",
- "unit": "%",
- "default_value": 100.0,
- "minimum_value": "0.001",
- "maximum_value_warning": "150",
- "settable_per_mesh": false,
- "settable_per_extruder": true
}
}
+ },
+ "initial_layer_line_width_factor":
+ {
+ "label": "Initial Layer Line Width",
+ "description": "Multiplier of the line width on the first layer. Increasing this could improve bed adhesion.",
+ "type": "float",
+ "unit": "%",
+ "default_value": 100.0,
+ "minimum_value": "0.001",
+ "maximum_value_warning": "150",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
}
}
},
@@ -1176,6 +1172,18 @@
"value": "999999 if infill_sparse_density == 100 else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))",
"limit_to_extruder": "top_bottom_extruder_nr",
"settable_per_mesh": true
+ },
+ "initial_bottom_layers":
+ {
+ "label": "Initial Bottom Layers",
+ "description": "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number.",
+ "minimum_value": "0",
+ "minimum_value_warning": "2",
+ "default_value": 6,
+ "type": "int",
+ "value": "bottom_layers",
+ "limit_to_extruder": "top_bottom_extruder_nr",
+ "settable_per_mesh": true
}
}
}
@@ -1315,8 +1323,7 @@
"default_value": 0,
"type": "float",
"enabled": "travel_compensate_overlapping_walls_0_enabled or travel_compensate_overlapping_walls_x_enabled",
- "settable_per_mesh": true,
- "settable_per_extruder": false
+ "settable_per_mesh": true
},
"wall_min_flow_retract":
{
@@ -1325,8 +1332,7 @@
"type": "bool",
"default_value": false,
"enabled": "(travel_compensate_overlapping_walls_0_enabled or travel_compensate_overlapping_walls_x_enabled) and wall_min_flow > 0",
- "settable_per_mesh": true,
- "settable_per_extruder": false
+ "settable_per_mesh": true
},
"fill_perimeter_gaps":
{
@@ -1399,41 +1405,66 @@
"limit_to_extruder": "wall_0_extruder_nr",
"settable_per_mesh": true
},
- "z_seam_x":
+ "z_seam_position":
{
- "label": "Z Seam X",
- "description": "The X coordinate of the position near where to start printing each part in a layer.",
- "unit": "mm",
- "type": "float",
- "default_value": 100.0,
- "value": "machine_width / 2",
+ "label": "Z Seam Position",
+ "description": "The position near where to start printing each part in a layer.",
+ "type": "enum",
+ "options":
+ {
+ "backleft": "Back Left",
+ "back": "Back",
+ "backright": "Back Right",
+ "right": "Right",
+ "frontright": "Front Right",
+ "front": "Front",
+ "frontleft": "Front Left",
+ "left": "Left"
+ },
"enabled": "z_seam_type == 'back'",
+ "default_value": "back",
"limit_to_extruder": "wall_0_extruder_nr",
- "settable_per_mesh": true
- },
- "z_seam_y":
- {
- "label": "Z Seam Y",
- "description": "The Y coordinate of the position near where to start printing each part in a layer.",
- "unit": "mm",
- "type": "float",
- "default_value": 100.0,
- "value": "machine_depth * 3",
- "enabled": "z_seam_type == 'back'",
- "limit_to_extruder": "wall_0_extruder_nr",
- "settable_per_mesh": true
+ "settable_per_mesh": true,
+ "children":
+ {
+ "z_seam_x":
+ {
+ "label": "Z Seam X",
+ "description": "The X coordinate of the position near where to start printing each part in a layer.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 100.0,
+ "value": "(0 if (z_seam_position == 'frontleft' or z_seam_position == 'left' or z_seam_position == 'backleft') else machine_width / 2 if (z_seam_position == 'front' or z_seam_position == 'back') else machine_width) - (machine_width / 2 if z_seam_relative or machine_center_is_zero else 0)",
+ "enabled": "z_seam_type == 'back'",
+ "limit_to_extruder": "wall_0_extruder_nr",
+ "settable_per_mesh": true
+ },
+ "z_seam_y":
+ {
+ "label": "Z Seam Y",
+ "description": "The Y coordinate of the position near where to start printing each part in a layer.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 100.0,
+ "value": "(0 if (z_seam_position == 'frontleft' or z_seam_position == 'front' or z_seam_position == 'frontright') else machine_depth / 2 if (z_seam_position == 'left' or z_seam_position == 'right') else machine_depth) - (machine_depth / 2 if z_seam_relative or machine_center_is_zero else 0)",
+ "enabled": "z_seam_type == 'back'",
+ "limit_to_extruder": "wall_0_extruder_nr",
+ "settable_per_mesh": true
+ }
+ }
},
"z_seam_corner":
{
"label": "Seam Corner Preference",
- "description": "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner.",
+ "description": "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner. Smart Hiding allows both inside and outside corners, but chooses inside corners more frequently, if appropriate.",
"type": "enum",
"options":
{
- "z_seam_corner_none": "None",
- "z_seam_corner_inner": "Hide Seam",
- "z_seam_corner_outer": "Expose Seam",
- "z_seam_corner_any": "Hide or Expose Seam"
+ "z_seam_corner_none": "None",
+ "z_seam_corner_inner": "Hide Seam",
+ "z_seam_corner_outer": "Expose Seam",
+ "z_seam_corner_any": "Hide or Expose Seam",
+ "z_seam_corner_weighted": "Smart Hiding"
},
"default_value": "z_seam_corner_inner",
"enabled": "z_seam_type != 'random'",
@@ -1453,8 +1484,8 @@
},
"skin_no_small_gaps_heuristic":
{
- "label": "Ignore Small Z Gaps",
- "description": "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting.",
+ "label": "No Skin in Z Gaps",
+ "description": "When the model has small vertical gaps of only a few layers, there should normally be skin around those layers in the narrow space. Enable this setting to not generate skin if the vertical gap is very small. This improves printing time and slicing time, but technically leaves infill exposed to the air.",
"type": "bool",
"default_value": false,
"enabled": "top_layers > 0 or bottom_layers > 0",
@@ -1476,7 +1507,7 @@
"ironing_enabled":
{
"label": "Enable Ironing",
- "description": "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface.",
+ "description": "Go over the top surface one additional time, but this time extruding very little material. This is meant to melt the plastic on top further, creating a smoother surface. The pressure in the nozzle chamber is kept high so that the creases in the surface are filled with material.",
"type": "bool",
"default_value": false,
"limit_to_extruder": "top_bottom_extruder_nr",
@@ -1590,6 +1621,36 @@
"enabled": "resolveOrValue('jerk_enabled') and ironing_enabled",
"limit_to_extruder": "top_bottom_extruder_nr",
"settable_per_mesh": true
+ },
+ "skin_overlap":
+ {
+ "label": "Skin Overlap Percentage",
+ "description": "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 5,
+ "minimum_value_warning": "-50",
+ "maximum_value_warning": "100",
+ "value": "5 if top_bottom_pattern != 'concentric' else 0",
+ "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'",
+ "limit_to_extruder": "top_bottom_extruder_nr",
+ "settable_per_mesh": true,
+ "children":
+ {
+ "skin_overlap_mm":
+ {
+ "label": "Skin Overlap",
+ "description": "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0.02,
+ "minimum_value_warning": "-0.5 * machine_nozzle_size",
+ "maximum_value_warning": "machine_nozzle_size",
+ "value": "0.5 * (skin_line_width + (wall_line_width_x if wall_line_count > 1 else wall_line_width_0)) * skin_overlap / 100 if top_bottom_pattern != 'concentric' else 0",
+ "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'",
+ "settable_per_mesh": true
+ }
+ }
}
}
},
@@ -1722,6 +1783,17 @@
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
+ "infill_randomize_start_location":
+ {
+ "label": "Randomize Infill Start",
+ "description": "Randomize which infill line is printed first. This prevents one segment becoming the strongest, but it does so at the cost of an additional travel move.",
+ "type": "bool",
+ "default_value": false,
+ "warning_value": "True if infill_pattern not in ('grid', 'triangles', 'trihexagon', 'cubic', 'cubicsubdiv', 'tetrahedral', 'quarter_cubic') else None",
+ "enabled": "not ((infill_pattern == 'cross' and connect_infill_polygons) or infill_pattern == 'concentric')",
+ "limit_to_extruder": "infill_extruder_nr",
+ "settable_per_mesh": true
+ },
"infill_multiplier":
{
"label": "Infill Line Multiplier",
@@ -1789,36 +1861,6 @@
}
}
},
- "skin_overlap":
- {
- "label": "Skin Overlap Percentage",
- "description": "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.",
- "unit": "%",
- "type": "float",
- "default_value": 5,
- "minimum_value_warning": "-50",
- "maximum_value_warning": "100",
- "value": "5 if top_bottom_pattern != 'concentric' else 0",
- "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'",
- "limit_to_extruder": "top_bottom_extruder_nr",
- "settable_per_mesh": true,
- "children":
- {
- "skin_overlap_mm":
- {
- "label": "Skin Overlap",
- "description": "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.",
- "unit": "mm",
- "type": "float",
- "default_value": 0.02,
- "minimum_value_warning": "-0.5 * machine_nozzle_size",
- "maximum_value_warning": "machine_nozzle_size",
- "value": "0.5 * (skin_line_width + (wall_line_width_x if wall_line_count > 1 else wall_line_width_0)) * skin_overlap / 100 if top_bottom_pattern != 'concentric' else 0",
- "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'",
- "settable_per_mesh": true
- }
- }
- },
"infill_wipe_dist":
{
"label": "Infill Wipe Distance",
@@ -1840,7 +1882,7 @@
"unit": "mm",
"type": "float",
"default_value": 0.1,
- "minimum_value": "resolveOrValue('layer_height') if infill_line_distance > 0 else -999999",
+ "minimum_value": "resolveOrValue('layer_height') / 2 if infill_line_distance > 0 else -999999",
"maximum_value_warning": "0.75 * machine_nozzle_size",
"maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8) if infill_line_distance > 0 else 999999",
"value": "resolveOrValue('layer_height')",
@@ -1924,7 +1966,7 @@
"description": "The largest width of skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing top/bottom skin at slanted surfaces in the model.",
"unit": "mm",
"type": "float",
- "default_value": 0,
+ "default_value": 1,
"value": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x",
"minimum_value": "0",
"enabled": "top_layers > 0 or bottom_layers > 0",
@@ -1938,7 +1980,7 @@
"description": "The largest width of top skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing top skin at slanted surfaces in the model.",
"unit": "mm",
"type": "float",
- "default_value": 0,
+ "default_value": 1,
"value": "skin_preshrink",
"minimum_value": "0",
"enabled": "top_layers > 0 or bottom_layers > 0",
@@ -1951,7 +1993,7 @@
"description": "The largest width of bottom skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing bottom skin at slanted surfaces in the model.",
"unit": "mm",
"type": "float",
- "default_value": 0,
+ "default_value": 1,
"value": "skin_preshrink",
"minimum_value": "0",
"enabled": "top_layers > 0 or bottom_layers > 0",
@@ -1966,7 +2008,7 @@
"description": "The distance the skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the walls on neighboring layers adhere better to the skin. Lower values save amount of material used.",
"unit": "mm",
"type": "float",
- "default_value": 2.8,
+ "default_value": 1,
"value": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x",
"minimum_value": "-skin_preshrink",
"limit_to_extruder": "top_bottom_extruder_nr",
@@ -1980,7 +2022,7 @@
"description": "The distance the top skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the walls on the layer above adhere better to the skin. Lower values save amount of material used.",
"unit": "mm",
"type": "float",
- "default_value": 2.8,
+ "default_value": 1,
"value": "expand_skins_expand_distance",
"minimum_value": "-top_skin_preshrink",
"enabled": "top_layers > 0 or bottom_layers > 0",
@@ -1993,7 +2035,7 @@
"description": "The distance the bottom skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the skin adhere better to the walls on the layer below. Lower values save amount of material used.",
"unit": "mm",
"type": "float",
- "default_value": 2.8,
+ "default_value": 1,
"value": "expand_skins_expand_distance",
"minimum_value": "-bottom_skin_preshrink",
"enabled": "top_layers > 0 or bottom_layers > 0",
@@ -2080,11 +2122,26 @@
"default_value": 210,
"minimum_value_warning": "0",
"maximum_value_warning": "285",
- "enabled": "machine_nozzle_temp_enabled",
+ "enabled": false,
"settable_per_extruder": true,
"settable_per_mesh": false,
"minimum_value": "-273.15"
},
+ "build_volume_temperature":
+ {
+ "label": "Build Volume Temperature",
+ "description": "The temperature of the environment to print in. If this is 0, the build volume temperature will not be adjusted.",
+ "unit": "°C",
+ "type": "float",
+ "default_value": 0,
+ "resolve": "min(extruderValues('build_volume_temperature'))",
+ "minimum_value": "-273.15",
+ "minimum_value_warning": "0",
+ "maximum_value_warning": "285",
+ "enabled": "machine_heated_build_volume",
+ "settable_per_mesh": false,
+ "settable_per_extruder": false
+ },
"material_print_temperature":
{
"label": "Printing Temperature",
@@ -2126,7 +2183,7 @@
"minimum_value": "-273.15",
"minimum_value_warning": "material_standby_temperature",
"maximum_value_warning": "material_print_temperature",
- "enabled": "machine_nozzle_temp_enabled",
+ "enabled": "machine_nozzle_temp_enabled and not machine_extruders_share_heater",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2141,7 +2198,7 @@
"minimum_value": "-273.15",
"minimum_value_warning": "material_standby_temperature",
"maximum_value_warning": "material_print_temperature",
- "enabled": "machine_nozzle_temp_enabled",
+ "enabled": "machine_nozzle_temp_enabled and not machine_extruders_share_heater",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2168,9 +2225,9 @@
"resolve": "max(extruderValues('default_material_bed_temperature'))",
"default_value": 60,
"minimum_value": "-273.15",
- "minimum_value_warning": "0",
+ "minimum_value_warning": "build_volume_temperature",
"maximum_value_warning": "130",
- "enabled": "machine_heated_bed and machine_gcode_flavor != \"UltiGCode\"",
+ "enabled": false,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -2185,7 +2242,7 @@
"value": "default_material_bed_temperature",
"resolve": "max(extruderValues('material_bed_temperature'))",
"minimum_value": "-273.15",
- "minimum_value_warning": "0",
+ "minimum_value_warning": "build_volume_temperature",
"maximum_value_warning": "130",
"enabled": "machine_heated_bed and machine_gcode_flavor != \"UltiGCode\"",
"settable_per_mesh": false,
@@ -2202,7 +2259,7 @@
"default_value": 60,
"value": "resolveOrValue('material_bed_temperature')",
"minimum_value": "-273.15",
- "minimum_value_warning": "max(extruderValues('material_bed_temperature'))",
+ "minimum_value_warning": "max(build_volume_temperature, max(extruderValues('material_bed_temperature')))",
"maximum_value_warning": "130",
"enabled": "machine_heated_bed and machine_gcode_flavor != \"UltiGCode\"",
"settable_per_mesh": false,
@@ -2247,6 +2304,121 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
+ "material_crystallinity":
+ {
+ "label": "Crystalline Material",
+ "description": "Is this material the type that breaks off cleanly when heated (crystalline), or is it the type that produces long intertwined polymer chains (non-crystalline)?",
+ "type": "bool",
+ "default_value": false,
+ "enabled": false,
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_anti_ooze_retracted_position":
+ {
+ "label": "Anti-ooze Retracted Position",
+ "description": "How far the material needs to be retracted before it stops oozing.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": -4,
+ "enabled": false,
+ "minimum_value_warning": "-retraction_amount",
+ "maximum_value_warning": "0",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_anti_ooze_retraction_speed":
+ {
+ "label": "Anti-ooze Retraction Speed",
+ "description": "How fast the material needs to be retracted during a filament switch to prevent oozing.",
+ "type": "float",
+ "unit": "mm/s",
+ "default_value": 5,
+ "enabled": false,
+ "minimum_value": "0",
+ "maximum_value": "machine_max_feedrate_e",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_break_preparation_retracted_position":
+ {
+ "label": "Break Preparation Retracted Position",
+ "description": "How far the filament can be stretched before it breaks, while heated.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": -16,
+ "enabled": false,
+ "minimum_value_warning": "-retraction_amount * 4",
+ "maximum_value_warning": "0",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_break_preparation_speed":
+ {
+ "label": "Break Preparation Retraction Speed",
+ "description": "How fast the filament needs to be retracted just before breaking it off in a retraction.",
+ "type": "float",
+ "unit": "mm/s",
+ "default_value": 2,
+ "enabled": false,
+ "minimum_value": "0",
+ "maximum_value": "machine_max_feedrate_e",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_break_preparation_temperature":
+ {
+ "label": "Break Preparation Temperature",
+ "description": "The temperature used to purge material, should be roughly equal to the highest possible printing temperature.",
+ "type": "float",
+ "unit": "°C",
+ "default_value": 50,
+ "value": "material_print_temperature",
+ "enabled": false,
+ "minimum_value": "-273.15",
+ "maximum_value_warning": "300",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_break_retracted_position":
+ {
+ "label": "Break Retracted Position",
+ "description": "How far to retract the filament in order to break it cleanly.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": -50,
+ "enabled": false,
+ "minimum_value_warning": "-100",
+ "maximum_value_warning": "0",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_break_speed":
+ {
+ "label": "Break Retraction Speed",
+ "description": "The speed at which to retract the filament in order to break it cleanly.",
+ "type": "float",
+ "unit": "mm/s",
+ "default_value": 25,
+ "enabled": false,
+ "minimum_value": "0",
+ "maximum_value": "machine_max_feedrate_e",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_break_temperature":
+ {
+ "label": "Break Temperature",
+ "description": "The temperature at which the filament is broken for a clean break.",
+ "type": "float",
+ "unit": "°C",
+ "default_value": 50,
+ "enabled": false,
+ "minimum_value": "-273.15",
+ "maximum_value_warning": "300",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
"material_flow":
{
"label": "Flow",
@@ -2258,7 +2430,196 @@
"minimum_value_warning": "50",
"maximum_value_warning": "150",
"enabled": "machine_gcode_flavor != \"UltiGCode\"",
- "settable_per_mesh": true
+ "settable_per_mesh": true,
+ "children":
+ {
+ "wall_material_flow":
+ {
+ "label": "Wall Flow",
+ "description": "Flow compensation on wall lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "limit_to_extruder": "wall_0_extruder_nr if wall_x_extruder_nr == wall_0_extruder_nr else -1",
+ "settable_per_mesh": true,
+ "children":
+ {
+ "wall_0_material_flow":
+ {
+ "label": "Outer Wall Flow",
+ "description": "Flow compensation on the outermost wall line.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "wall_material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "limit_to_extruder": "wall_0_extruder_nr",
+ "settable_per_mesh": true
+ },
+ "wall_x_material_flow":
+ {
+ "label": "Inner Wall(s) Flow",
+ "description": "Flow compensation on wall lines for all wall lines except the outermost one.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "wall_material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "limit_to_extruder": "wall_x_extruder_nr",
+ "settable_per_mesh": true
+ }
+ }
+ },
+ "skin_material_flow":
+ {
+ "label": "Top/Bottom Flow",
+ "description": "Flow compensation on top/bottom lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "top_layers > 0 or bottom_layers > 0",
+ "limit_to_extruder": "top_bottom_extruder_nr",
+ "settable_per_mesh": true
+ },
+ "roofing_material_flow":
+ {
+ "label": "Top Surface Skin Flow",
+ "description": "Flow compensation on lines of the areas at the top of the print.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "skin_material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "limit_to_extruder": "roofing_extruder_nr",
+ "settable_per_mesh": true,
+ "enabled": "roofing_layer_count > 0 and top_layers > 0"
+ },
+ "infill_material_flow":
+ {
+ "label": "Infill Flow",
+ "description": "Flow compensation on infill lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "infill_sparse_density > 0",
+ "limit_to_extruder": "infill_extruder_nr",
+ "settable_per_mesh": true
+ },
+ "skirt_brim_material_flow":
+ {
+ "label": "Skirt/Brim Flow",
+ "description": "Flow compensation on skirt or brim lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim'",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_material_flow":
+ {
+ "label": "Support Flow",
+ "description": "Flow compensation on support structure lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "support_enable",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_interface_material_flow":
+ {
+ "label": "Support Interface Flow",
+ "description": "Flow compensation on lines of support roof or floor.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "support_enable and support_interface_enable",
+ "limit_to_extruder": "support_interface_extruder_nr",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "children":
+ {
+ "support_roof_material_flow":
+ {
+ "label": "Support Roof Flow",
+ "description": "Flow compensation on support roof lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "extruderValue(support_roof_extruder_nr, 'support_interface_material_flow')",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "support_enable and support_roof_enable",
+ "limit_to_extruder": "support_roof_extruder_nr",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_bottom_material_flow":
+ {
+ "label": "Support Floor Flow",
+ "description": "Flow compensation on support floor lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_material_flow')",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "support_enable and support_bottom_enable",
+ "limit_to_extruder": "support_bottom_extruder_nr",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
+ },
+ "prime_tower_flow":
+ {
+ "label": "Prime Tower Flow",
+ "description": "Flow compensation on prime tower lines.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 100,
+ "value": "material_flow",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
},
"material_flow_layer_0":
{
@@ -2266,7 +2627,6 @@
"description": "Flow compensation for the first layer: the amount of material extruded on the initial layer is multiplied by this value.",
"unit": "%",
"default_value": 100,
- "value": "material_flow",
"type": "float",
"minimum_value": "0.0001",
"minimum_value_warning": "50",
@@ -2378,7 +2738,6 @@
"minimum_value": "0",
"minimum_value_warning": "line_width * 1.5",
"maximum_value_warning": "10",
- "enabled": "retraction_enable",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2411,10 +2770,10 @@
"limit_support_retractions":
{
"label": "Limit Support Retractions",
- "description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure.",
+ "description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure.",
"type": "bool",
"default_value": true,
- "enabled": "retraction_enable and support_enable",
+ "enabled": "retraction_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2495,6 +2854,19 @@
"settable_per_extruder": true
}
}
+ },
+ "switch_extruder_extra_prime_amount":
+ {
+ "label": "Nozzle Switch Extra Prime Amount",
+ "description": "Extra material to prime after nozzle switching.",
+ "type": "float",
+ "unit": "mm³",
+ "default_value": 0,
+ "minimum_value_warning": "0",
+ "maximum_value_warning": "100",
+ "enabled": "retraction_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
}
}
},
@@ -2619,7 +2991,7 @@
"maximum_value_warning": "150",
"default_value": 60,
"value": "speed_print",
- "enabled": "support_enable",
+ "enabled": "support_enable or support_tree_enable",
"settable_per_mesh": false,
"limit_to_extruder": "support_extruder_nr",
"settable_per_extruder": true,
@@ -2636,7 +3008,7 @@
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"value": "speed_support",
- "enabled": "support_enable",
+ "enabled": "support_enable or support_tree_enable",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -2651,7 +3023,7 @@
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
- "enabled": "support_interface_enable and support_enable",
+ "enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_interface_extruder_nr",
"value": "speed_support / 1.5",
"settable_per_mesh": false,
@@ -2668,7 +3040,7 @@
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
- "enabled": "support_roof_enable and support_enable",
+ "enabled": "support_roof_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_roof_extruder_nr",
"value": "extruderValue(support_roof_extruder_nr, 'speed_support_interface')",
"settable_per_mesh": false,
@@ -2684,7 +3056,7 @@
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
- "enabled": "support_bottom_enable and support_enable",
+ "enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_bottom_extruder_nr",
"value": "extruderValue(support_bottom_extruder_nr, 'speed_support_interface')",
"settable_per_mesh": false,
@@ -2784,16 +3156,16 @@
"settable_per_extruder": true,
"limit_to_extruder": "adhesion_extruder_nr"
},
- "max_feedrate_z_override":
+ "speed_z_hop":
{
- "label": "Maximum Z Speed",
- "description": "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed.",
+ "label": "Z Hop Speed",
+ "description": "The speed at which the vertical Z movement is made for Z Hops. This is typically lower than the print speed since the build plate or machine's gantry is harder to move.",
"unit": "mm/s",
"type": "float",
- "default_value": 0,
+ "default_value": 10,
"minimum_value": "0",
- "maximum_value": "299792458000",
- "maximum_value_warning": "machine_max_feedrate_z",
+ "maximum_value": "machine_max_feedrate_z",
+ "enabled": "retraction_enable and retraction_hop_enabled",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2959,7 +3331,7 @@
"maximum_value_warning": "10000",
"default_value": 3000,
"value": "acceleration_print",
- "enabled": "resolveOrValue('acceleration_enabled') and support_enable",
+ "enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"limit_to_extruder": "support_extruder_nr",
"settable_per_extruder": true,
@@ -2976,7 +3348,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
- "enabled": "resolveOrValue('acceleration_enabled') and support_enable",
+ "enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -2992,7 +3364,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
- "enabled": "resolveOrValue('acceleration_enabled') and support_interface_enable and support_enable",
+ "enabled": "resolveOrValue('acceleration_enabled') and support_interface_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true,
@@ -3009,7 +3381,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
- "enabled": "acceleration_enabled and support_roof_enable and support_enable",
+ "enabled": "acceleration_enabled and support_roof_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3025,7 +3397,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
- "enabled": "acceleration_enabled and support_bottom_enable and support_enable",
+ "enabled": "acceleration_enabled and support_bottom_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3244,7 +3616,7 @@
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
- "enabled": "resolveOrValue('jerk_enabled') and support_enable",
+ "enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_extruder_nr",
@@ -3260,7 +3632,7 @@
"value": "jerk_support",
"minimum_value": "0",
"maximum_value_warning": "50",
- "enabled": "resolveOrValue('jerk_enabled') and support_enable",
+ "enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3275,7 +3647,7 @@
"value": "jerk_support",
"minimum_value": "0",
"maximum_value_warning": "50",
- "enabled": "resolveOrValue('jerk_enabled') and support_interface_enable and support_enable",
+ "enabled": "resolveOrValue('jerk_enabled') and support_interface_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true,
@@ -3291,7 +3663,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')",
"minimum_value": "0",
"maximum_value_warning": "50",
- "enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and support_enable",
+ "enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3306,7 +3678,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')",
"minimum_value": "0",
"maximum_value_warning": "50",
- "enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and support_enable",
+ "enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and (support_enable or support_tree_enable)",
"limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3484,17 +3856,6 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
- "start_layers_at_same_position":
- {
- "label": "Start Layers with the Same Part",
- "description": "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time.",
- "type": "bool",
- "default_value": false,
- "enabled": false,
- "settable_per_mesh": false,
- "settable_per_extruder": false,
- "settable_per_meshgroup": true
- },
"layer_start_x":
{
"label": "Layer Start X",
@@ -3557,6 +3918,20 @@
"enabled": "retraction_hop_enabled and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": true
+ },
+ "retraction_hop_after_extruder_switch_height":
+ {
+ "label": "Z Hop After Extruder Switch Height",
+ "description": "The height difference when performing a Z Hop after extruder switch.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 1,
+ "value": "retraction_hop",
+ "minimum_value_warning": "0",
+ "maximum_value_warning": "10",
+ "enabled": "retraction_enable and retraction_hop_after_extruder_switch and extruders_enabled_count > 1",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
}
}
},
@@ -3732,7 +4107,7 @@
"description": "The extruder train to use for printing the support. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
- "value": "defaultExtruderPosition()",
+ "value": "int(defaultExtruderPosition())",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false,
@@ -3870,7 +4245,7 @@
"type": "bool",
"default_value": false,
"value": "support_pattern == 'cross' or support_pattern == 'gyroid'",
- "enabled": "support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross' or support_pattern == 'gyroid'",
+ "enabled": "(support_enable or support_tree_enable) and (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross' or support_pattern == 'gyroid')",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3934,16 +4309,14 @@
}
}
},
- "support_infill_angle":
+ "support_infill_angles":
{
- "label": "Support Infill Line Direction",
- "description": "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane.",
- "unit": "°",
- "type": "float",
- "minimum_value": "-180",
- "maximum_value": "180",
- "default_value": 0,
- "enabled": "support_enable and support_pattern != 'concentric' and support_infill_rate > 0",
+ "label": "Support Infill Line Directions",
+ "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees.",
+ "type": "[int]",
+ "default_value": "[ ]",
+ "enabled": "(support_enable or support_tree_enable) and support_pattern != 'concentric' and support_infill_rate > 0",
+ "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -3967,7 +4340,7 @@
"default_value": 8.0,
"minimum_value": "0.0",
"maximum_value_warning": "50.0",
- "enabled": "support_enable",
+ "enabled": "(support_enable or support_tree_enable) and support_brim_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr",
@@ -3982,7 +4355,7 @@
"minimum_value": "0",
"maximum_value_warning": "50 / skirt_brim_line_width",
"value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))",
- "enabled": "support_enable",
+ "enabled": "(support_enable or support_tree_enable) and support_brim_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr"
@@ -4068,6 +4441,7 @@
"unit": "mm",
"type": "float",
"minimum_value": "0",
+ "minimum_value_warning": "support_xy_distance - support_line_width * 2",
"maximum_value_warning": "support_xy_distance",
"default_value": 0.2,
"value": "machine_nozzle_size / 2",
@@ -4104,7 +4478,7 @@
"support_join_distance":
{
"label": "Support Join Distance",
- "description": "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one.",
+ "description": "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one.",
"unit": "mm",
"type": "float",
"default_value": 2.0,
@@ -4120,7 +4494,7 @@
"description": "Amount of offset applied to all support polygons in each layer. Positive values can smooth out the support areas and result in more sturdy support.",
"unit": "mm",
"type": "float",
- "default_value": 0.2,
+ "default_value": 0,
"limit_to_extruder": "support_infill_extruder_nr",
"minimum_value_warning": "-1 * machine_nozzle_size",
"maximum_value_warning": "10 * machine_nozzle_size",
@@ -4271,7 +4645,7 @@
"minimum_value": "0",
"maximum_value_warning": "support_interface_height",
"limit_to_extruder": "support_interface_extruder_nr",
- "enabled": "support_interface_enable and support_enable",
+ "enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true
},
"support_interface_density":
@@ -4422,21 +4796,21 @@
"minimum_interface_area":
{
"label": "Minimum Support Interface Area",
- "description": "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated.",
+ "description": "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will be printed as normal support.",
"unit": "mm²",
"type": "float",
"default_value": 1.0,
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_interface_extruder_nr",
- "enabled": "support_interface_enable and support_enable",
+ "enabled": "support_interface_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true,
"children":
{
"minimum_roof_area":
{
"label": "Minimum Support Roof Area",
- "description": "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated.",
+ "description": "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will be printed as normal support.",
"unit": "mm²",
"type": "float",
"default_value": 1.0,
@@ -4444,13 +4818,13 @@
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_roof_extruder_nr",
- "enabled": "support_roof_enable and support_enable",
+ "enabled": "support_roof_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true
},
"minimum_bottom_area":
{
"label": "Minimum Support Floor Area",
- "description": "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated.",
+ "description": "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will be printed as normal support.",
"unit": "mm²",
"type": "float",
"default_value": 1.0,
@@ -4458,7 +4832,7 @@
"minimum_value": "0",
"minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_bottom_extruder_nr",
- "enabled": "support_bottom_enable and support_enable",
+ "enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
"settable_per_mesh": true
}
}
@@ -4507,13 +4881,51 @@
}
}
},
+ "support_interface_angles":
+ {
+ "label": "Support Interface Line Directions",
+ "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees).",
+ "type": "[int]",
+ "default_value": "[ ]",
+ "limit_to_extruder": "support_interface_extruder_nr",
+ "enabled": "(support_enable or support_tree_enable) and support_interface_enable and support_interface_pattern != 'concentric'",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "children":
+ {
+ "support_roof_angles":
+ {
+ "label": "Support Roof Line Directions",
+ "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees).",
+ "type": "[int]",
+ "default_value": "[ ]",
+ "value": "support_interface_angles",
+ "limit_to_extruder": "support_roof_extruder_nr",
+ "enabled": "(support_enable or support_tree_enable) and support_roof_enable and support_roof_pattern != 'concentric'",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_bottom_angles":
+ {
+ "label": "Support Floor Line Directions",
+ "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees).",
+ "type": "[int]",
+ "default_value": "[ ]",
+ "value": "support_interface_angles",
+ "limit_to_extruder": "support_bottom_extruder_nr",
+ "enabled": "(support_enable or support_tree_enable) and support_bottom_enable and support_bottom_pattern != 'concentric'",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
+ },
"support_fan_enable":
{
"label": "Fan Speed Override",
"description": "When enabled, the print cooling fan speed is altered for the skin regions immediately above the support.",
"type": "bool",
"default_value": false,
- "enabled": "support_enable",
+ "enabled": "support_enable or support_tree_enable",
"settable_per_mesh": false
},
"support_supported_skin_fan_speed":
@@ -4525,7 +4937,7 @@
"maximum_value": "100",
"default_value": 100,
"type": "float",
- "enabled": "support_enable and support_fan_enable",
+ "enabled": "(support_enable or support_tree_enable) and support_fan_enable",
"settable_per_mesh": false
},
"support_use_towers":
@@ -4552,10 +4964,10 @@
"enabled": "support_enable and support_use_towers",
"settable_per_mesh": true
},
- "support_minimal_diameter":
+ "support_tower_maximum_supported_diameter":
{
- "label": "Minimum Diameter",
- "description": "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower.",
+ "label": "Maximum Tower-Supported Diameter",
+ "description": "Maximum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower.",
"unit": "mm",
"type": "float",
"default_value": 3.0,
@@ -4607,11 +5019,11 @@
"label": "Enable Prime Blob",
"description": "Whether to prime the filament with a blob before printing. Turning this setting on will ensure that the extruder will have material ready at the nozzle before printing. Printing Brim or Skirt can act like priming too, in which case turning this setting off saves some time.",
"type": "bool",
- "resolve": "any(extruderValues('prime_blob_enable'))",
"default_value": false,
"settable_per_mesh": false,
"settable_per_extruder": true,
- "enabled": false
+ "enabled": false,
+ "warning_value": "True if resolveOrValue('print_sequence') == 'one_at_a_time' else None"
},
"extruder_prime_pos_x":
{
@@ -4662,7 +5074,7 @@
"description": "The extruder train to use for printing the skirt/brim/raft. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
- "value": "defaultExtruderPosition()",
+ "value": "int(defaultExtruderPosition())",
"enabled": "extruders_enabled_count > 1 and (resolveOrValue('adhesion_type') != 'none' or resolveOrValue('prime_tower_brim_enable'))",
"settable_per_mesh": false,
"settable_per_extruder": false
@@ -4747,7 +5159,7 @@
"description": "Enforce brim to be printed around the model even if that space would otherwise be occupied by support. This replaces some regions of the first layer of support by brim regions.",
"type": "bool",
"default_value": true,
- "enabled": "resolveOrValue('adhesion_type') == 'brim' and support_enable",
+ "enabled": "resolveOrValue('adhesion_type') == 'brim' and (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr"
@@ -5249,18 +5661,7 @@
"type": "bool",
"enabled": "extruders_enabled_count > 1",
"default_value": false,
- "resolve": "any(extruderValues('prime_tower_enable'))",
- "settable_per_mesh": false,
- "settable_per_extruder": false
- },
- "prime_tower_circular":
- {
- "label": "Circular Prime Tower",
- "description": "Make the prime tower as a circular shape.",
- "type": "bool",
- "enabled": "resolveOrValue('prime_tower_enable')",
- "default_value": true,
- "resolve": "any(extruderValues('prime_tower_circular'))",
+ "resolve": "(extruders_enabled_count > 1) and any(extruderValues('prime_tower_enable'))",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -5288,7 +5689,7 @@
"type": "float",
"default_value": 6,
"minimum_value": "0",
- "maximum_value_warning": "((resolveOrValue('prime_tower_size') * 0.5) ** 2 * 3.14159 * resolveOrValue('layer_height') if prime_tower_circular else resolveOrValue('prime_tower_size') ** 2 * resolveOrValue('layer_height')) - sum(extruderValues('prime_tower_min_volume')) + prime_tower_min_volume",
+ "maximum_value_warning": "(resolveOrValue('prime_tower_size') * 0.5) ** 2 * 3.14159 * resolveOrValue('layer_height')",
"enabled": "resolveOrValue('prime_tower_enable')",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -5301,7 +5702,7 @@
"unit": "mm",
"enabled": "resolveOrValue('prime_tower_enable')",
"default_value": 200,
- "value": "machine_width - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enable') else 0) - 1",
+ "value": "machine_width - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1",
"maximum_value": "machine_width / 2 if machine_center_is_zero else machine_width",
"minimum_value": "resolveOrValue('prime_tower_size') - machine_width / 2 if machine_center_is_zero else resolveOrValue('prime_tower_size')",
"settable_per_mesh": false,
@@ -5315,27 +5716,12 @@
"unit": "mm",
"enabled": "resolveOrValue('prime_tower_enable')",
"default_value": 200,
- "value": "machine_depth - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enable') else 0) - 1",
+ "value": "machine_depth - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1",
"maximum_value": "machine_depth / 2 - resolveOrValue('prime_tower_size') if machine_center_is_zero else machine_depth - resolveOrValue('prime_tower_size')",
"minimum_value": "machine_depth / -2 if machine_center_is_zero else 0",
"settable_per_mesh": false,
"settable_per_extruder": false
},
- "prime_tower_flow":
- {
- "label": "Prime Tower Flow",
- "description": "Flow compensation: the amount of material extruded is multiplied by this value.",
- "type": "float",
- "unit": "%",
- "enabled": "resolveOrValue('prime_tower_enable')",
- "default_value": 100,
- "value": "material_flow",
- "minimum_value": "0.0001",
- "minimum_value_warning": "50",
- "maximum_value_warning": "150",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
"prime_tower_wipe_enabled":
{
"label": "Wipe Inactive Nozzle on Prime Tower",
@@ -5352,6 +5738,7 @@
"description": "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type.",
"type": "bool",
"enabled": "resolveOrValue('prime_tower_enable') and (resolveOrValue('adhesion_type') != 'raft')",
+ "resolve": "resolveOrValue('prime_tower_enable') and (resolveOrValue('adhesion_type') in ('none', 'skirt'))",
"default_value": false,
"settable_per_mesh": false,
"settable_per_extruder": false
@@ -5478,9 +5865,47 @@
"description": "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle.",
"type": "bool",
"default_value": true,
- "enabled": "not support_enable",
+ "enabled": "not (support_enable or support_tree_enable)",
"settable_per_mesh": false,
"settable_per_extruder": false
+ },
+ "meshfix_maximum_resolution":
+ {
+ "label": "Maximum Resolution",
+ "description": "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": 0.5,
+ "minimum_value": "0.001",
+ "minimum_value_warning": "0.01",
+ "maximum_value_warning": "3",
+ "settable_per_mesh": true
+ },
+ "meshfix_maximum_travel_resolution":
+ {
+ "label": "Maximum Travel Resolution",
+ "description": "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": 1.0,
+ "value": "min(meshfix_maximum_resolution * speed_travel / speed_print, 2 * line_width)",
+ "minimum_value": "0.001",
+ "minimum_value_warning": "0.05",
+ "maximum_value_warning": "10",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "meshfix_maximum_deviation":
+ {
+ "label": "Maximum Deviation",
+ "description": "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": 0.05,
+ "minimum_value": "0.001",
+ "minimum_value_warning": "0.01",
+ "maximum_value_warning": "0.3",
+ "settable_per_mesh": true
}
}
},
@@ -5638,7 +6063,7 @@
"smooth_spiralized_contours":
{
"label": "Smooth Spiralized Contours",
- "description": "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details.",
+ "description": "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details.",
"type": "bool",
"default_value": true,
"enabled": "magic_spiralize",
@@ -5840,6 +6265,7 @@
"label": "Infill Travel Optimization",
"description": "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased.",
"type": "bool",
+ "enabled": "resolveOrValue('retraction_combing') != 'off'",
"default_value": false,
"settable_per_mesh": true
},
@@ -5871,38 +6297,12 @@
"unit": "mm",
"type": "float",
"default_value": 1.0,
- "minimum_value": "0.001",
+ "minimum_value": "0",
"minimum_value_warning": "0.05",
"maximum_value_warning": "1.0",
"settable_per_mesh": true,
"settable_per_extruder": false
},
- "meshfix_maximum_resolution":
- {
- "label": "Maximum Resolution",
- "description": "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway.",
- "type": "float",
- "unit": "mm",
- "default_value": 0.01,
- "minimum_value": "0.001",
- "minimum_value_warning": "0.005",
- "maximum_value_warning": "0.1",
- "settable_per_mesh": true
- },
- "meshfix_maximum_travel_resolution":
- {
- "label": "Maximum Travel Resolution",
- "description": "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate.",
- "type": "float",
- "unit": "mm",
- "default_value": 0.02,
- "value": "meshfix_maximum_resolution * speed_travel / speed_print",
- "minimum_value": "0.001",
- "minimum_value_warning": "0.005",
- "maximum_value_warning": "1",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
"support_skip_some_zags":
{
"label": "Break Up Support In Chunks",
@@ -6065,16 +6465,6 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
- "skin_alternate_rotation":
- {
- "label": "Alternate Skin Rotation",
- "description": "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions.",
- "type": "bool",
- "default_value": false,
- "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'",
- "limit_to_extruder": "top_bottom_extruder_nr",
- "settable_per_mesh": true
- },
"cross_infill_pocket_size":
{
"label": "Cross 3D Pocket Size",
@@ -6199,7 +6589,7 @@
"support_conical_enabled":
{
"label": "Enable Conical Support",
- "description": "Experimental feature: Make support areas smaller at the bottom than at the overhang.",
+ "description": "Make support areas smaller at the bottom than at the overhang.",
"type": "bool",
"default_value": false,
"enabled": "support_enable",
@@ -6231,7 +6621,7 @@
"minimum_value_warning": "machine_nozzle_size * 3",
"maximum_value_warning": "100.0",
"type": "float",
- "enabled": "support_conical_enabled and support_enable",
+ "enabled": "support_conical_enabled and support_enable and support_conical_angle > 0",
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": true
},
@@ -6292,30 +6682,26 @@
},
"flow_rate_max_extrusion_offset":
{
- "label": "Flow rate compensation max extrusion offset",
- "description": "The maximum distance in mm to compensate.",
+ "label": "Flow Rate Compensation Max Extrusion Offset",
+ "description": "The maximum distance in mm to move the filament to compensate for changes in flow rate.",
"unit": "mm",
"type": "float",
"minimum_value": "0",
"maximum_value_warning": "10",
"default_value": 0,
- "value": "0",
- "enabled": true,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
"flow_rate_extrusion_offset_factor":
{
- "label": "Flow rate compensation factor",
- "description": "The multiplication factor for the flow rate -> distance translation.",
+ "label": "Flow Rate Compensation Factor",
+ "description": "How far to move the filament in order to compensate for changes in flow rate, as a percentage of how far the filament would move in one second of extrusion.",
"unit": "%",
"type": "float",
"minimum_value": "0",
"maximum_value_warning": "100",
"default_value": 100,
- "value": "100",
- "enabled": true,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -6338,7 +6724,7 @@
"unit": "mm",
"default_value": 3,
"value": "machine_nozzle_head_distance",
- "minimum_value": "0.0001",
+ "minimum_value": "0.001",
"maximum_value_warning": "20",
"enabled": "wireframe_enabled",
"settable_per_mesh": false,
@@ -6368,8 +6754,8 @@
"unit": "mm/s",
"type": "float",
"default_value": 5,
- "minimum_value": "0.1",
- "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2 + max(max_feedrate_z_override, machine_max_feedrate_z) ** 2)",
+ "minimum_value": "0.05",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2 + machine_max_feedrate_z ** 2)",
"maximum_value_warning": "50",
"enabled": "wireframe_enabled",
"settable_per_mesh": false,
@@ -6384,11 +6770,11 @@
"unit": "mm/s",
"type": "float",
"default_value": 5,
- "minimum_value": "0.1",
+ "minimum_value": "0.05",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "50",
"enabled": "wireframe_enabled",
- "value": "wireframe_printspeed",
+ "value": "wireframe_printspeed_flat",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -6400,8 +6786,8 @@
"unit": "mm/s",
"type": "float",
"default_value": 5,
- "minimum_value": "0.1",
- "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2 + max(max_feedrate_z_override, machine_max_feedrate_z) ** 2)",
+ "minimum_value": "0.05",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2 + machine_max_feedrate_z ** 2)",
"maximum_value_warning": "50",
"enabled": "wireframe_enabled",
"value": "wireframe_printspeed",
@@ -6416,8 +6802,8 @@
"unit": "mm/s",
"type": "float",
"default_value": 5,
- "minimum_value": "0.1",
- "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2 + max(max_feedrate_z_override, machine_max_feedrate_z) ** 2)",
+ "minimum_value": "0.05",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2 + machine_max_feedrate_z ** 2)",
"maximum_value_warning": "50",
"enabled": "wireframe_enabled",
"value": "wireframe_printspeed",
@@ -6432,7 +6818,7 @@
"unit": "mm/s",
"type": "float",
"default_value": 5,
- "minimum_value": "0.1",
+ "minimum_value": "0.05",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "100",
"value": "wireframe_printspeed",
@@ -6555,7 +6941,7 @@
"default_value": 0.6,
"minimum_value": "0",
"maximum_value_warning": "2.0",
- "enabled": "wireframe_enabled",
+ "enabled": "wireframe_enabled and wireframe_strategy == 'knot'",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -6569,7 +6955,7 @@
"default_value": 0.5,
"minimum_value": "0",
"maximum_value_warning": "wireframe_height",
- "enabled": "wireframe_enabled",
+ "enabled": "wireframe_enabled and wireframe_strategy == 'compensate'",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -6583,7 +6969,7 @@
"default_value": 0.6,
"minimum_value": "0",
"maximum_value_warning": "wireframe_height",
- "enabled": "wireframe_enabled",
+ "enabled": "wireframe_enabled and wireframe_strategy == 'compensate'",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -6677,7 +7063,7 @@
},
"adaptive_layer_height_enabled":
{
- "label": "Use adaptive layers",
+ "label": "Use Adaptive Layers",
"description": "Adaptive layers computes the layer heights depending on the shape of the model.",
"type": "bool",
"default_value": false,
@@ -6687,7 +7073,7 @@
},
"adaptive_layer_height_variation":
{
- "label": "Adaptive layers maximum variation",
+ "label": "Adaptive Layers Maximum Variation",
"description": "The maximum allowed height different from the base layer height.",
"type": "float",
"enabled": "adaptive_layer_height_enabled",
@@ -6699,23 +7085,25 @@
},
"adaptive_layer_height_variation_step":
{
- "label": "Adaptive layers variation step size",
+ "label": "Adaptive Layers Variation Step Size",
"description": "The difference in height of the next layer height compared to the previous one.",
"type": "float",
"enabled": "adaptive_layer_height_enabled",
"default_value": 0.01,
"unit": "mm",
"settable_per_mesh": false,
+ "minimum_value": "0.001",
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
"adaptive_layer_height_threshold":
{
- "label": "Adaptive layers threshold",
- "description": "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer.",
+ "label": "Adaptive Layers Topography Size",
+ "description": "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together.",
"type": "float",
"enabled": "adaptive_layer_height_enabled",
- "default_value": 200.0,
+ "default_value": 0.2,
+ "unit": "mm",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -6723,7 +7111,7 @@
"wall_overhang_angle":
{
"label": "Overhanging Wall Angle",
- "description": "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging.",
+ "description": "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging. Overhang that gets supported by support will not be treated as overhang either.",
"unit": "°",
"type": "float",
"minimum_value": "0",
@@ -6777,6 +7165,17 @@
"enabled": "bridge_settings_enabled",
"settable_per_mesh": true
},
+ "bridge_sparse_infill_max_density":
+ {
+ "label": "Bridge Sparse Infill Max Density",
+ "description": "Maximum density of infill considered to be sparse. Skin over sparse infill is considered to be unsupported and so may be treated as a bridge skin.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 0,
+ "minimum_value": "0",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
"bridge_wall_coast":
{
"label": "Bridge Wall Coasting",
@@ -6982,44 +7381,303 @@
"type": "float",
"enabled": "bridge_settings_enabled and bridge_enable_more_layers",
"settable_per_mesh": true
+ },
+ "clean_between_layers":
+ {
+ "label": "Wipe Nozzle Between Layers",
+ "description": "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working.",
+ "default_value": false,
+ "type": "bool",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "max_extrusion_before_wipe":
+ {
+ "label": "Material Volume Between Wipes",
+ "description": "Maximum material, that can be extruded before another nozzle wipe is initiated.",
+ "default_value": 10,
+ "type": "float",
+ "unit": "mm³",
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_retraction_enable":
+ {
+ "label": "Wipe Retraction Enable",
+ "description": "Retract the filament when the nozzle is moving over a non-printed area.",
+ "type": "bool",
+ "default_value": true,
+ "value": "retraction_enable",
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_retraction_amount":
+ {
+ "label": "Wipe Retraction Distance",
+ "description": "Amount to retract the filament so it does not ooze during the wipe sequence.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 1,
+ "value": "retraction_amount",
+ "minimum_value_warning": "-0.0001",
+ "maximum_value_warning": "10.0",
+ "enabled": "wipe_retraction_enable and clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_retraction_extra_prime_amount":
+ {
+ "label": "Wipe Retraction Extra Prime Amount",
+ "description": "Some material can ooze away during a wipe travel moves, which can be compensated for here.",
+ "unit": "mm³",
+ "type": "float",
+ "default_value": 0,
+ "value": "retraction_extra_prime_amount",
+ "minimum_value_warning": "-0.0001",
+ "maximum_value_warning": "10.0",
+ "enabled": "wipe_retraction_enable and clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "wipe_retraction_speed":
+ {
+ "label": "Wipe Retraction Speed",
+ "description": "The speed at which the filament is retracted and primed during a wipe retraction move.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 5,
+ "value": "retraction_speed",
+ "minimum_value": "0",
+ "minimum_value_warning": "1",
+ "maximum_value": "machine_max_feedrate_e",
+ "maximum_value_warning": "70",
+ "enabled": "wipe_retraction_enable and clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "children":
+ {
+ "wipe_retraction_retract_speed":
+ {
+ "label": "Wipe Retraction Retract Speed",
+ "description": "The speed at which the filament is retracted during a wipe retraction move.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 3,
+ "minimum_value": "0",
+ "maximum_value": "machine_max_feedrate_e",
+ "minimum_value_warning": "1",
+ "maximum_value_warning": "70",
+ "enabled": "wipe_retraction_enable and clean_between_layers",
+ "value": "wipe_retraction_speed",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "wipe_retraction_prime_speed":
+ {
+ "label": "Wipe Retraction Prime Speed",
+ "description": "The speed at which the filament is primed during a wipe retraction move.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 2,
+ "minimum_value": "0",
+ "maximum_value": "machine_max_feedrate_e",
+ "minimum_value_warning": "1",
+ "maximum_value_warning": "70",
+ "enabled": "wipe_retraction_enable and clean_between_layers",
+ "value": "wipe_retraction_speed",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
+ },
+ "wipe_pause":
+ {
+ "label": "Wipe Pause",
+ "description": "Pause after the unretract.",
+ "unit": "s",
+ "type": "float",
+ "default_value": 0,
+ "minimum_value": "0",
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_hop_enable":
+ {
+ "label": "Wipe Z Hop",
+ "description": "When wiping, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate.",
+ "type": "bool",
+ "default_value": true,
+ "value": "retraction_hop_enabled",
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_hop_amount":
+ {
+ "label": "Wipe Z Hop Height",
+ "description": "The height difference when performing a Z Hop.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 1,
+ "value": "retraction_hop",
+ "enabled": "wipe_hop_enable and clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_hop_speed":
+ {
+ "label": "Wipe Hop Speed",
+ "description": "Speed to move the z-axis during the hop.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 10,
+ "value": "speed_z_hop",
+ "minimum_value": "0",
+ "minimum_value_warning": "1",
+ "enabled": "wipe_hop_enable and clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_brush_pos_x":
+ {
+ "label": "Wipe Brush X Position",
+ "description": "X location where wipe script will start.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": 100,
+ "minimum_value_warning": "0",
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_repeat_count":
+ {
+ "label": "Wipe Repeat Count",
+ "description": "Number of times to move the nozzle across the brush.",
+ "type": "int",
+ "minimum_value": "0",
+ "default_value": 5,
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "wipe_move_distance":
+ {
+ "label": "Wipe Move Distance",
+ "description": "The distance to move the head back and forth across the brush.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 20,
+ "enabled": "clean_between_layers",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "settable_per_meshgroup": false
+ },
+ "small_hole_max_size":
+ {
+ "label": "Small Hole Max Size",
+ "description": "Holes and part outlines with a diameter smaller than this will be printed using Small Feature Speed.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0",
+ "default_value": 0,
+ "settable_per_mesh": true,
+ "children":
+ {
+ "small_feature_max_length":
+ {
+ "label": "Small Feature Max Length",
+ "description": "Feature outlines that are shorter than this length will be printed using Small Feature Speed.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0",
+ "default_value": 0,
+ "value": "small_hole_max_size * math.pi",
+ "settable_per_mesh": true
+ }
+ }
+ },
+ "small_feature_speed_factor":
+ {
+ "label": "Small Feature Speed",
+ "description": "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 50,
+ "minimum_value": "1",
+ "minimum_value_warning": "25",
+ "maximum_value": "100",
+ "settable_per_mesh": true
+ },
+ "small_feature_speed_factor_0":
+ {
+ "label": "Small Feature Initial Layer Speed",
+ "description": "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy.",
+ "unit": "%",
+ "type": "float",
+ "default_value": 50,
+ "value": "small_feature_speed_factor",
+ "minimum_value": "1",
+ "minimum_value_warning": "25",
+ "maximum_value": "100",
+ "settable_per_mesh": true
}
}
},
- "command_line_settings": {
+ "command_line_settings":
+ {
"label": "Command Line Settings",
"description": "Settings which are only used if CuraEngine isn't called from the Cura frontend.",
"type": "category",
"enabled": false,
"children": {
- "center_object": {
+ "center_object":
+ {
"description": "Whether to center the object on the middle of the build platform (0,0), instead of using the coordinate system in which the object was saved.",
"type": "bool",
"label": "Center Object",
"default_value": false,
"enabled": false
},
- "mesh_position_x": {
+ "mesh_position_x":
+ {
"description": "Offset applied to the object in the x direction.",
"type": "float",
"label": "Mesh Position X",
"default_value": 0,
"enabled": false
},
- "mesh_position_y": {
+ "mesh_position_y":
+ {
"description": "Offset applied to the object in the y direction.",
"type": "float",
"label": "Mesh Position Y",
"default_value": 0,
"enabled": false
},
- "mesh_position_z": {
+ "mesh_position_z":
+ {
"description": "Offset applied to the object in the z direction. With this you can perform what was used to be called 'Object Sink'.",
"type": "float",
"label": "Mesh Position Z",
"default_value": 0,
"enabled": false
},
- "mesh_rotation_matrix": {
+ "mesh_rotation_matrix":
+ {
"label": "Mesh Rotation Matrix",
"description": "Transformation matrix to be applied to the model when loading it from file.",
"type": "str",
diff --git a/resources/definitions/felixpro2dual.def.json b/resources/definitions/felixpro2dual.def.json
new file mode 100644
index 0000000000..fdd8a1b694
--- /dev/null
+++ b/resources/definitions/felixpro2dual.def.json
@@ -0,0 +1,71 @@
+{
+ "version": 2,
+ "name": "Felix Pro 2 Dual",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "pnks",
+ "manufacturer": "Felix",
+ "platform": "FelixPro2_platform.obj",
+ "platform_offset": [-135, -0.5, 130],
+ "machine_extruder_trains":
+ {
+ "0": "felixpro2_dual_extruder_0",
+ "1": "felixpro2_dual_extruder_1"
+ },
+ "file_formats": "text/x-gcode",
+ "has_variants": true,
+ "has_materials": true,
+ "preferred_variant_name": "0.35 mm",
+ "variants_name": "Nozzle diameter"
+ },
+ "overrides": {
+ "machine_name": { "default_value": "FelixPro2Dual" },
+
+ "layer_height": { "default_value": 0.15 },
+ "layer_height_0": { "default_value": 0.2 },
+
+ "infill_sparse_density": { "default_value": 20 },
+ "wall_thickness": { "default_value": 1 },
+ "top_bottom_thickness": { "default_value": 1 },
+
+ "machine_width": { "default_value": 240 },
+ "machine_depth": { "default_value": 225 },
+ "machine_height": { "default_value": 245 },
+
+ "machine_head_with_fans_polygon":
+ {
+ "default_value": [
+ [ -60, 50 ],
+ [ -60, -50 ],
+ [ 70, 50 ],
+ [ 70, -50 ]
+ ]
+ },
+ "gantry_height": { "value": "0" },
+ "machine_extruder_count": { "default_value": 2 },
+ "prime_tower_position_x": { "value": "250" },
+ "prime_tower_position_y": { "value": "200" },
+
+ "machine_heated_bed": { "default_value": true },
+ "machine_gcode_flavor": { "default_value": "Repetier" },
+ "machine_center_is_zero": { "default_value": false },
+
+ "speed_print": { "default_value": 80 },
+
+ "retraction_amount": { "default_value": 1 },
+ "retraction_speed": { "default_value": 50},
+ "material_flow": { "default_value": 100 },
+ "material_flow_layer_0": { "default_value" : 110, "value": "material_flow * 1.1" },
+ "adhesion_type": { "default_value": "skirt" },
+ "skirt_brim_minimal_length": { "default_value": 130 },
+ "skirt_line_count": { "default_value": 3 },
+
+ "machine_start_gcode": {
+ "default_value": "G90 ;absolute positioning\r\nM82 ;set extruder to absolute mode\r\nM107 ;start with the fan off\r\nG28 X0 Y0 ;move X\/Y to min endstops\r\nG28 Z0 ;move Z to min endstops\r\nG1 Z15.0 F9000 ;move the platform down 15mm\r\n\r\nT0 ;Switch to the 1st extruder\r\nG92 E0 ;zero the extruded length\r\nG1 F200 E6 ;extrude 6 mm of feed stock\r\nG92 E0 ;zero the extruded length again\r\n;G1 F9000\r\nM117 FPro2 printing...\r\n"
+ },
+ "machine_end_gcode": {
+ "default_value": "; Endcode FELIXprinters Pro series\r\n; =================================\t; Move extruder to park position\r\nG91 \t\t\t\t\t; Make coordinates relative\r\nG1 Z2 F5000 \t\t\t\t; Move z 2mm up\r\nG90 \t\t\t\t\t; Use absolute coordinates again\t\t\r\nG1 X220 Y243 F7800 \t\t\t; Move bed and printhead to ergonomic position\r\n\r\n; =================================\t; Turn off heaters\r\nT0\t\t\t\t\t; Select left extruder\r\nM104 T0 S0\t\t\t\t; Turn off heater and continue\t\t\t\t\r\nG92 E0\t\t\t\t\t; Reset extruder position\r\nG1 E-8\t\t\t\t\t; Retract filament 8mm\r\nG1 E-5\t\t\t\t\t; Push back filament 3mm\r\nG92 E0\t\t\t\t\t; Reset extruder position\r\n\r\nT1\t\t\t\t\t; Select right extruder\r\nM104 T1 S0\t\t\t\t; Turn off heater and continu\r\nG92 E0\t\t\t\t\t; Reset extruder position\r\nG1 E-8\t\t\t\t\t; Retract filament 8mm\r\nG1 E-5\t\t\t\t\t; Push back filament 3mm\r\nG92 E0\t\t\t\t\t; Reset extruder position\r\nT0\t\t\t\t\t; Select left extruder\r\nM140 S0\t\t\t\t\t; Turn off bed heater\r\n\r\n; =================================\t; Turn the rest off\r\nM107 \t\t\t\t; Turn off fan\r\nM84\t\t\t\t\t; Disable steppers\r\nM117 Print Complete"
+ }
+ }
+}
diff --git a/resources/definitions/felixtec4dual.def.json b/resources/definitions/felixtec4dual.def.json
index ba5bcfa112..efc13c1759 100644
--- a/resources/definitions/felixtec4dual.def.json
+++ b/resources/definitions/felixtec4dual.def.json
@@ -39,7 +39,6 @@
"machine_center_is_zero": { "default_value": false },
"speed_print": { "default_value": 60 },
- "speed_travel": { "default_value": 200 },
"retraction_amount": { "default_value": 1 },
"retraction_speed": { "default_value": 50},
diff --git a/resources/definitions/flsun_qq.def.json b/resources/definitions/flsun_qq.def.json
index ce69317b33..02b3849c12 100644
--- a/resources/definitions/flsun_qq.def.json
+++ b/resources/definitions/flsun_qq.def.json
@@ -19,13 +19,13 @@
"default_value": true
},
"machine_width": {
- "default_value": 240
+ "default_value": 260
},
"machine_height": {
"default_value": 285
},
"machine_depth": {
- "default_value": 240
+ "default_value": 260
},
"machine_center_is_zero": {
"default_value": true
diff --git a/resources/definitions/flsun_qq_s.def.json b/resources/definitions/flsun_qq_s.def.json
new file mode 100644
index 0000000000..9c3bf571ae
--- /dev/null
+++ b/resources/definitions/flsun_qq_s.def.json
@@ -0,0 +1,71 @@
+{
+ "version": 2,
+ "name": "FLSUN QQ-S",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Cataldo URSO",
+ "manufacturer": "FLSUN",
+ "file_formats": "text/x-gcode",
+ "has_materials": true,
+ "preferred_quality_type": "draft",
+ "machine_extruder_trains": {
+ "0": "flsun_qq_s_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_center_is_zero": {
+ "default_value": true
+ },
+ "machine_shape": {
+ "default_value": "elliptic"
+ },
+ "machine_width": {
+ "default_value": 260
+ },
+ "machine_depth": {
+ "default_value": 260
+ },
+ "machine_height": {
+ "default_value": 370
+ },
+ "z_seam_type": {
+ "default_value": "back"
+ },
+ "gantry_height": {
+ "value": "0"
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_start_gcode": {
+ "default_value": "G21\nG90\nM82\nM107 T0\nM190 S{material_bed_temperature}\nM109 S{material_print_temperature} T0\nG28\nG92 E0\nG0 E3 F200\nG92 E0\n"
+ },
+ "machine_end_gcode": {
+ "default_value": "M107 T0\nM104 S0\nM104 S0 T1\nM140 S0\nG92 E0\nG91\nG1 E-1 F300 \nG1 Z+0.5 E-5 X-20 Y-20 F9000\nG28 X0 Y0\nM84 ;steppers off\nG90 ;absolute positioning\n"
+ },
+ "infill_sparse_density": {
+ "default_value": 10
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [0, 0],
+ [0, 0],
+ [0, 0],
+ [0, 0]
+ ]
+ },
+ "retraction_enable": {
+ "default_value": true
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_gcode_flavor": {
+ "default_value": "Repetier"
+ }
+ }
+}
diff --git a/resources/definitions/folgertech_FT-5.def.json b/resources/definitions/folgertech_FT-5.def.json
index d3d00a9b25..7ede40a025 100644
--- a/resources/definitions/folgertech_FT-5.def.json
+++ b/resources/definitions/folgertech_FT-5.def.json
@@ -18,7 +18,7 @@
"machine_width": { "default_value": 300 },
"machine_height": { "default_value": 400 },
"machine_depth": { "default_value": 300 },
- "gantry_height": { "default_value": 55 },
+ "gantry_height": { "value": "55" },
"machine_start_gcode": {
"default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
diff --git a/resources/definitions/geeetech_a30.def.json b/resources/definitions/geeetech_a30.def.json
new file mode 100644
index 0000000000..1f08d37445
--- /dev/null
+++ b/resources/definitions/geeetech_a30.def.json
@@ -0,0 +1,113 @@
+{
+ "version": 2,
+ "name": "Geeetech A30",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "author": "William & Cataldo URSO",
+ "manufacturer": "Shenzhen Geeetech Technology",
+ "file_formats": "text/x-gcode",
+ "visible": true,
+ "has_materials": true,
+ "preferred_quality_type": "draft",
+ "machine_extruder_trains": {
+ "0": "geeetech_a30_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Geeetech A30"
+ },
+ "machine_start_gcode": {
+ "default_value": "G28 ;Home\nM190 S{material_bed_temperature}\nM109 S{material_print_temperature} T0\nG1 Z15.0 F6000 ;Move the platform down 15mm\nG92 E0\nG1 F200 E3\nG92 E0"
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0;Cooling the heat end\nM140 S0;Cooling the heat bed\nG92 E1\nG1 E-1 F300\nG28 X0 Y0;Home X axis and Y axis\nM84"
+ },
+ "machine_width": {
+ "default_value": 320
+ },
+ "machine_height": {
+ "default_value": 420
+ },
+ "machine_depth": {
+ "default_value": 320
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "layer_height": {
+ "default_value": 0.1
+ },
+ "layer_height_0": {
+ "default_value": 0.3
+ },
+ "retraction_amount": {
+ "default_value": 2
+ },
+ "retraction_speed": {
+ "default_value": 25
+ },
+ "adhesion_type": {
+ "default_value": "skirt"
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-75, 35],
+ [18, 35],
+ [18, -18],
+ [-75, -18]
+ ]
+ },
+ "gantry_height": {
+ "value": "55"
+ },
+ "machine_max_feedrate_x": {
+ "default_value": 300
+ },
+ "machine_max_feedrate_y": {
+ "default_value": 300
+ },
+ "machine_max_feedrate_z": {
+ "default_value": 7
+ },
+ "machine_max_feedrate_e": {
+ "default_value": 50
+ },
+ "machine_max_acceleration_x": {
+ "default_value": 2000
+ },
+ "machine_max_acceleration_y": {
+ "default_value": 2000
+ },
+ "machine_max_acceleration_z": {
+ "default_value": 100
+ },
+ "machine_max_acceleration_e": {
+ "default_value": 10000
+ },
+ "machine_acceleration": {
+ "default_value": 2000
+ },
+ "machine_max_jerk_xy": {
+ "default_value": 10
+ },
+ "machine_max_jerk_z": {
+ "default_value": 1
+ },
+ "machine_max_jerk_e": {
+ "default_value": 5
+ },
+ "machine_gcode_flavor": {
+ "default_value": "Repetier"
+ }
+ }
+}
diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json
index 069b8be999..e98d6c02fe 100644
--- a/resources/definitions/gmax15plus.def.json
+++ b/resources/definitions/gmax15plus.def.json
@@ -1,5 +1,4 @@
{
- "id": "gmax15plus",
"version": 2,
"name": "gMax 1.5 Plus",
"inherits": "fdmprinter",
@@ -37,9 +36,8 @@
"retraction_amount": { "default_value": 1 },
"retraction_speed": { "default_value": 70},
"adhesion_type": { "default_value": "skirt" },
- "gantry_height": { "default_value": 50 },
+ "gantry_height": { "value": "50" },
"speed_print": { "default_value": 50 },
- "speed_travel": { "default_value": 70 },
"machine_max_acceleration_x": { "default_value": 600 },
"machine_max_acceleration_y": { "default_value": 600 },
"machine_max_acceleration_z": { "default_value": 30 },
@@ -50,9 +48,7 @@
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": { "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;Home X/Y/Z\nM104 S{material_print_temperature} ; Preheat\nM109 S{material_print_temperature} ; Preheat\nG91 ;relative positioning\nG90 ;absolute positioning\nG1 Z25.0 F9000 ;raise nozzle 25mm\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." },
"machine_end_gcode": { "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" },
- "material_print_temperature": { "default_value": 202 },
"wall_thickness": { "default_value": 1 },
- "top_bottom_thickness": { "default_value": 1 },
- "bottom_thickness": { "default_value": 1 }
+ "top_bottom_thickness": { "default_value": 1 }
}
}
diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json
index 0264ef5977..aaba2cc55b 100644
--- a/resources/definitions/gmax15plus_dual.def.json
+++ b/resources/definitions/gmax15plus_dual.def.json
@@ -1,5 +1,4 @@
{
- "id": "gmax15plus_dual",
"version": 2,
"name": "gMax 1.5 Plus Dual Extruder",
"inherits": "fdmprinter",
@@ -35,9 +34,8 @@
"retraction_amount": { "default_value": 1 },
"retraction_speed": { "default_value": 70},
"adhesion_type": { "default_value": "skirt" },
- "gantry_height": { "default_value": 50 },
+ "gantry_height": { "value": "50" },
"speed_print": { "default_value": 50 },
- "speed_travel": { "default_value": 70 },
"machine_max_acceleration_x": { "default_value": 600 },
"machine_max_acceleration_y": { "default_value": 600 },
"machine_max_acceleration_z": { "default_value": 30 },
@@ -48,9 +46,7 @@
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": { "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;Home X/Y/Z\nM104 S{material_print_temperature} T0 ; Preheat Left Extruder\nM104 S{material_print_temperature} T1 ; Preheat Right Extruder\nM109 S{material_print_temperature} T0 ; Preheat Left Extruder\nM109 S{material_print_temperature} T1 ; Preheat Right Extruder\nG91 ;relative positioning\nG90 ;absolute positioning\nM218 T1 X34.3 Y0; Set 2nd extruder offset. This can be changed later if needed\nG1 Z25.0 F9000 ;raise nozzle 25mm\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." },
"machine_end_gcode": { "default_value": "M104 S0 T0;Left extruder off\nM104 S0 T1; Right extruder off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" },
- "material_print_temperature": { "default_value": 202 },
"wall_thickness": { "default_value": 1 },
- "top_bottom_thickness": { "default_value": 1 },
- "bottom_thickness": { "default_value": 1 }
+ "top_bottom_thickness": { "default_value": 1 }
}
}
diff --git a/resources/definitions/grr_neo.def.json b/resources/definitions/grr_neo.def.json
index 67d6a92023..774a3e614c 100644
--- a/resources/definitions/grr_neo.def.json
+++ b/resources/definitions/grr_neo.def.json
@@ -28,7 +28,7 @@
"machine_center_is_zero": {
"default_value": false
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
[-75, -18],
[-75, 35],
@@ -37,7 +37,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/hellbot_adonis.def.json b/resources/definitions/hellbot_adonis.def.json
new file mode 100644
index 0000000000..a73c66a611
--- /dev/null
+++ b/resources/definitions/hellbot_adonis.def.json
@@ -0,0 +1,32 @@
+{
+ "version": 2,
+ "name": "Hellbot Adonis",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "MUX team",
+ "manufacturer": "Hellbot",
+ "file_formats": "text/x-gcode",
+ "platform": "hellbot_adonis.obj",
+ "platform_texture": "hellbot.png",
+ "platform_offset": [0, -1, 0],
+ "has_materials": true,
+ "machine_extruder_trains": {
+ "0": "hellbot_adonis_extruder"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Hellbot Adonis"
+ },
+ "machine_width": {
+ "default_value": 160
+ },
+ "machine_depth": {
+ "default_value": 160
+ },
+ "machine_height": {
+ "default_value": 160
+ }
+ }
+}
diff --git a/resources/definitions/hellbot_magna_I.def.json b/resources/definitions/hellbot_magna_I.def.json
new file mode 100644
index 0000000000..453dcef718
--- /dev/null
+++ b/resources/definitions/hellbot_magna_I.def.json
@@ -0,0 +1,32 @@
+{
+ "version": 2,
+ "name": "Hellbot Magna 1",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "MUX team",
+ "manufacturer": "Hellbot",
+ "file_formats": "text/x-gcode",
+ "platform": "hellbot_magna.obj",
+ "platform_texture": "hellbot.png",
+ "platform_offset": [0, -1, 0],
+ "has_materials": true,
+ "machine_extruder_trains": {
+ "0": "hellbot_magna_i_extruder"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Hellbot Magna 1"
+ },
+ "machine_width": {
+ "default_value": 220
+ },
+ "machine_depth": {
+ "default_value": 220
+ },
+ "machine_height": {
+ "default_value": 260
+ }
+ }
+}
diff --git a/resources/definitions/hellbot_magna_dual.def.json b/resources/definitions/hellbot_magna_dual.def.json
new file mode 100644
index 0000000000..5ee36e0749
--- /dev/null
+++ b/resources/definitions/hellbot_magna_dual.def.json
@@ -0,0 +1,36 @@
+{
+ "version": 2,
+ "name": "Hellbot Magna DUAL",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "MUX team",
+ "manufacturer": "Hellbot",
+ "file_formats": "text/x-gcode",
+ "platform": "hellbot_magna.obj",
+ "platform_texture": "hellbot.png",
+ "platform_offset": [0, -1, 0],
+ "has_materials": true,
+ "machine_extruder_trains": {
+ "0": "hellbot_magna_dual_extruder_1",
+ "1": "hellbot_magna_dual_extruder_2"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Hellbot Magna DUAL"
+ },
+ "machine_width": {
+ "default_value": 220
+ },
+ "machine_depth": {
+ "default_value": 220
+ },
+ "machine_height": {
+ "default_value": 260
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ }
+ }
+}
diff --git a/resources/definitions/helloBEEprusa.def.json b/resources/definitions/helloBEEprusa.def.json
index 65716ac175..2c8c4839d0 100644
--- a/resources/definitions/helloBEEprusa.def.json
+++ b/resources/definitions/helloBEEprusa.def.json
@@ -26,28 +26,15 @@
"machine_height": { "default_value": 190 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
- "material_print_temperature": { "default_value": 200 },
- "material_bed_temperature": { "default_value": 60 },
- "line_width": { "default_value": 0.48 },
"layer_height": { "default_value": 0.2 },
"layer_height_0": { "default_value": 0.2 },
- "wall_line_count": { "default_value": 3 },
"wall_thickness": { "default_value": 1.2 },
"top_bottom_thickness": { "default_value": 1.2 },
"infill_sparse_density": { "default_value": 20 },
- "infill_overlap": { "default_value": 15 },
"speed_print": { "default_value": 60 },
- "speed_travel": { "default_value": 160 },
- "speed_layer_0": { "default_value": 30 },
- "speed_wall_x": { "default_value": 35 },
- "speed_wall_0": { "default_value": 30 },
- "speed_infill": { "default_value": 60 },
- "speed_topbottom": { "default_value": 20 },
- "skirt_brim_speed": { "default_value": 35 },
"skirt_line_count": { "default_value": 4 },
"skirt_brim_minimal_length": { "default_value": 30 },
"skirt_gap": { "default_value": 6 },
- "cool_fan_full_at_height": { "default_value": 0.4 },
"retraction_speed": { "default_value": 15.0},
"retraction_amount": { "default_value": 1.5}
}
diff --git a/resources/definitions/hms434.def.json b/resources/definitions/hms434.def.json
new file mode 100644
index 0000000000..ca031f26bf
--- /dev/null
+++ b/resources/definitions/hms434.def.json
@@ -0,0 +1,187 @@
+{
+ "name": "HMS434",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Scheepers",
+ "manufacturer": "Hybrid AM Systems",
+ "file_formats": "text/x-gcode",
+
+ "has_materials": true,
+ "preferred_material": "generic_pla",
+ "exclude_materials": [
+ "chromatik_pla",
+ "dsm_arnitel2045_175", "dsm_novamid1070_175",
+ "emotiontech_abs", "emotiontech_petg", "emotiontech_pla", "emotiontech_pva-m", "emotiontech_pva-oks", "emotiontech_pva-s", "emotiontech_tpu98a",
+ "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu",
+ "fiberlogy_hd_pla",
+ "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red",
+ "generic_abs_175", "generic_cpe_175", "generic_hips_175", "generic_nylon_175", "generic_pc_175", "generic_petg_175", "generic_pva_175", "generic_tpu_175",
+ "imade3d_petg_175", "imade3d_pla_175",
+ "innofill_innoflex60_175",
+ "octofiber_pla",
+ "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla",
+ "verbatim_bvoh_175",
+ "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_PLA_Glitter", "Vertex_Delta_PLA_Mat", "Vertex_Delta_PLA_Satin", "Vertex_Delta_PLA_Wood", "Vertex_Delta_TPU",
+ "tizyx_abs", "tizyx_flex", "tizyx_petg", "tizyx_pla", "tizyx_pla_bois", "tizyx_pva",
+ "zyyx_pro_flex", "zyyx_pro_pla"
+ ],
+
+ "has_variants": true,
+ "variants_name": "Tool",
+ "preferred_variant_name": "0.4mm TP extruder",
+
+ "has_machine_quality": true,
+ "preferred_quality_type": "normal",
+
+ "machine_extruder_trains":
+ {
+ "0": "hms434_tool_1",
+ "1": "hms434_tool_2",
+ "2": "hms434_tool_3",
+ "3": "hms434_tool_4",
+ "4": "hms434_tool_5",
+ "5": "hms434_tool_6",
+ "6": "hms434_tool_7",
+ "7": "hms434_tool_8"
+ },
+ "platform": "hms_platform.obj",
+ "platform_offset": [ 26, -13.2, 162.5],
+ "platform_texture": "hms434.png",
+ "first_start_actions": ["MachineSettingsAction"],
+ "supported_actions": ["MachineSettingsAction"]
+ },
+
+ "overrides": {
+ "machine_extruder_count": {"default_value": 2 },
+ "material_diameter": {"default_value": 1.75 },
+ "machine_heated_bed": {"default_value": true },
+ "machine_heated_build_volume":{"default_value": true },
+ "machine_center_is_zero": {"default_value": false },
+ "gantry_height": {"value": "35" },
+ "machine_height": {"default_value": 400 },
+ "machine_depth": {"default_value": 325 },
+ "machine_width": {"default_value": 450 },
+ "machine_gcode_flavor": {"default_value": "RepRap (RepRap)" },
+ "material_print_temp_wait": {"default_value": false },
+ "material_bed_temp_wait": {"default_value": false },
+ "machine_max_feedrate_z": {"default_value": 10 },
+ "machine_acceleration": {"default_value": 1000 },
+ "machine_start_gcode": {"default_value": "\n;Neither Hybrid AM Systems nor any of Hybrid AM Systems representatives has any liabilities or gives any warranties on this .gcode file, or on any or all objects made with this .gcode file.\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\n\nG1 X-44 Y-100 F9000;go to wipe point\nG1 Z0 F900\nG1 Z0.2 F900\nM117 HMS434 Printing ...\n\n" },
+ "machine_end_gcode": {"default_value": "" },
+
+ "retraction_extra_prime_amount": {"minimum_value_warning": "-2.0" },
+ "optimize_wall_printing_order": {"default_value": true },
+ "machine_nozzle_heat_up_speed": {"default_value": 12},
+ "machine_nozzle_cool_down_speed": {"default_value": 20},
+ "machine_min_cool_heat_time_window": {"default_value": 5},
+
+ "layer_height": {"maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
+ "layer_height_0": {"maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
+ "line_width": {"value": "(machine_nozzle_size + layer_height)" },
+ "infill_line_width": {"value": "(line_width)" },
+ "initial_layer_line_width_factor": {"value": 110 },
+
+ "wall_thickness": {"value": "(line_width * 3) if infill_sparse_density < 95 else line_width" },
+ "roofing_layer_count": {"value": "4" },
+ "top_bottom_thickness": {"value": "(layer_height_0 + (layer_height * 3))" },
+ "top_layers": {"value": "4" },
+ "bottom_layers": {"value": "(top_layers)" },
+ "wall_0_inset": {"value": "0" },
+ "outer_inset_first": {"value": true },
+ "alternate_extra_perimeter": {"value": false },
+ "filter_out_tiny_gaps": {"value": false },
+ "fill_outline_gaps": {"value": true },
+ "skin_outline_count": {"value": "0"},
+ "ironing_enabled": {"value": true },
+ "ironing_line_spacing": {"value": "line_width"},
+ "ironing_flow": {"value": "0"},
+ "ironing_inset": {"value": "line_width"},
+ "speed_ironing": {"value": "150"},
+
+ "infill_sparse_density": {"value": 30},
+ "infill_pattern": {"value": "'lines'"},
+ "infill_overlap": {"value": 5},
+ "skin_overlap": {"value": 5},
+ "infill_wipe_dist": {"value": 0.0},
+ "infill_before_walls": {"value": false},
+
+ "material_print_temperature_layer_0": {"value": "material_print_temperature + 5"},
+ "material_initial_print_temperature": {"value": "material_print_temperature",
+ "maximum_value_warning": "material_print_temperature + 15"},
+ "material_final_print_temperature": {"value": "material_print_temperature"},
+ "material_bed_temperature_layer_0": {"value": "material_bed_temperature + 1"},
+ "material_flow": {"value": "100"},
+ "retraction_amount": {"value": "1"},
+ "retraction_speed": {"value": "20"},
+ "retraction_prime_speed": {"value": "8"},
+ "retraction_min_travel": {"value": "(round(line_width * 10))"},
+ "switch_extruder_retraction_amount": {"value": 2},
+ "switch_extruder_retraction_speeds": {"value": "(retraction_speed)"},
+ "switch_extruder_prime_speed": {"value": "(retraction_prime_speed)"},
+
+ "speed_print": {"value": "50"},
+ "speed_infill": {"value": "speed_print"},
+ "speed_wall": {"value": "(speed_print/5*3) if speed_print < 51 else speed_print"},
+ "speed_wall_x": {"value": "speed_wall"},
+ "speed_layer_0": {"value": "(speed_print/5*4) if speed_print < 51 else speed_print"},
+ "speed_topbottom": {"value": "speed_layer_0"},
+ "speed_travel": {"value": "150"},
+ "speed_travel_layer_0": {"value": "speed_travel"},
+ "speed_support_interface": {"value": "speed_topbottom"},
+ "speed_z_hop": {"value": 10},
+ "speed_slowdown_layers": {"value": 1},
+ "acceleration_print": {"value": 1000},
+ "acceleration_travel": {"value": 1000},
+ "jerk_print": {"value": 10},
+ "jerk_travel": {"value": 10},
+
+ "retraction_hop_enabled": {"value": false},
+ "retraction_hop": {"value": 1},
+ "retraction_combing": {"value": "'off'"},
+
+ "cool_fan_speed": {"value": 0},
+ "cool_fan_enabled": {"value": true},
+ "cool_min_layer_time_fan_speed_max": {"value": "cool_min_layer_time"},
+ "cool_min_layer_time": {"value": 20},
+ "cool_min_speed": {"value": "10"},
+ "cool_lift_head": {"value": false},
+
+ "support_z_distance": {"value": 0},
+ "support_xy_distance": {"value": 1},
+ "support_join_distance": {"value": 10},
+ "support_interface_enable": {"value": true},
+ "support_interface_height": {"value": 0.5},
+ "support_interface_pattern": {"value": "'lines'"},
+
+ "adhesion_type": {"value": "'none'"},
+ "skirt_gap": {"value": 1},
+ "skirt_brim_minimal_length": {"value": 50},
+
+ "prime_tower_enable": {"value": false },
+ "prime_tower_size": {"value": 20.6 },
+ "prime_tower_position_x": {"value": 125 },
+ "prime_tower_position_y": {"value": 70 },
+ "prime_blob_enable": {"default_value": false },
+
+ "coasting_enable": {"value": true},
+ "coasting_volume": {"value": 0.1},
+ "coasting_min_volume": {"value": 0.17},
+ "coasting_speed": {"value": 90},
+ "bridge_settings_enabled": {"value": true},
+ "bridge_wall_min_length": {"value": 3},
+ "bridge_skin_support_threshold": {"value": 90},
+ "bridge_wall_speed": {"value": 15},
+ "bridge_wall_material_flow": {"value": 130},
+ "bridge_skin_speed": {"value": 15},
+ "bridge_skin_material_flow": {"value": 130},
+ "bridge_fan_speed": {"value": 0},
+ "bridge_skin_density_2": {"value": 100},
+ "bridge_skin_density_3": {"value": 100},
+ "bridge_skin_material_flow_2": {"value": 110},
+ "bridge_skin_material_flow_3": {"value": 100},
+ "bridge_skin_speed_2": {"value": 20},
+ "bridge_skin_speed_3": {"value": 30}
+ }
+}
diff --git a/resources/definitions/imade3d_jellybox.def.json b/resources/definitions/imade3d_jellybox.def.json
index ae9ca176f5..635cb1fdd0 100644
--- a/resources/definitions/imade3d_jellybox.def.json
+++ b/resources/definitions/imade3d_jellybox.def.json
@@ -1,19 +1,16 @@
{
"version": 2,
- "name": "IMADE3D JellyBOX",
- "inherits": "fdmprinter",
+ "name": "IMADE3D JellyBOX Original",
+ "inherits": "imade3d_jellybox_root",
"metadata": {
"visible": true,
"author": "IMADE3D",
- "manufacturer": "IMADE3D",
"platform": "imade3d_jellybox_platform.stl",
"platform_offset": [ 0, -0.3, 0],
- "file_formats": "text/x-gcode",
"preferred_variant_name": "0.4 mm",
"preferred_quality_type": "fast",
"has_materials": true,
"has_variants": true,
- "has_machine_materials": true,
"has_machine_quality": true,
"machine_extruder_trains": {
"0": "imade3d_jellybox_extruder_0"
@@ -22,18 +19,15 @@
"overrides": {
"machine_head_with_fans_polygon": { "default_value": [[ 0, 0 ],[ 0, 0 ],[ 0, 0 ],[ 0, 0 ]]},
- "machine_name": { "default_value": "IMADE3D JellyBOX" },
+ "machine_name": { "default_value": "IMADE3D JellyBOX Original" },
"machine_width": { "default_value": 170 },
"machine_height": { "default_value": 145 },
"machine_depth": { "default_value": 160 },
- "machine_heated_bed": { "default_value": true },
- "machine_center_is_zero": { "default_value": false },
- "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
- "default_value": ";---------------------------------------\n; ; ; Jellybox Start Script Begin ; ; ;\n;_______________________________________\n; M92 E140 ;optionally adjust steps per mm for your filament\n\n; Print Settings Summary\n; (leave these alone: this is only a list of the slicing settings)\n; (overwriting these values will NOT change your printer's behavior)\n; sliced for : {machine_name}\n; nozzle diameter : {machine_nozzle_size}\n; filament diameter : {material_diameter}\n; layer height : {layer_height}\n; 1st layer height : {layer_height_0}\n; line width : {line_width}\n; outer wall wipe dist. : {wall_0_wipe_dist}\n; infill line width : {infill_line_width}\n; wall thickness : {wall_thickness}\n; top thickness : {top_thickness}\n; bottom thickness : {bottom_thickness}\n; infill density : {infill_sparse_density}\n; infill pattern : {infill_pattern}\n; print temperature : {material_print_temperature}\n; 1st layer print temp. : {material_print_temperature_layer_0}\n; heated bed temperature : {material_bed_temperature}\n; 1st layer bed temp. : {material_bed_temperature_layer_0}\n; regular fan speed : {cool_fan_speed_min}\n; max fan speed : {cool_fan_speed_max}\n; retraction amount : {retraction_amount}\n; retr. retract speed : {retraction_retract_speed}\n; retr. prime speed : {retraction_prime_speed}\n; build plate adhesion : {adhesion_type}\n; support ? {support_enable}\n; spiralized ? {magic_spiralize}\n\nM117 Preparing ;write Preparing\nM140 S{material_bed_temperature_layer_0} ;set bed temperature and move on\nM109 S{material_print_temperature} ; wait for the extruder to reach desired temperature\nM206 X10.0 Y0.0 ;set x homing offset for default bed leveling\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nM82 ;set extruder to absolute mode\nG28 ;home all axes\nM203 Z4 ;slow Z speed down for greater accuracy when probing\nG29 ;auto bed leveling procedure\nM203 Z7 ;pick up z speed again for printing\nM190 S{material_bed_temperature_layer_0} ;wait for the bed to reach desired temperature\nM109 S{material_print_temperature_layer_0} ;wait for the extruder to reach desired temperature\nG92 E0 ;reset the extruder position\nG1 F1500 E15 ;extrude 15mm of feed stock\nG92 E0 ;reset the extruder position again\nM117 Print starting ;write Print starting\n;---------------------------------------------\n; ; ; Jellybox Printer Start Script End ; ; ;\n;_____________________________________________\n"
+ "default_value": ";---------------------------------------\n; ; ; Jellybox Start Script Begin ; ; ;\n;_______________________________________\n; for slicer: CURA 3\n; start gcode last modified Jun 1, 2019\n\n; Print Settings Summary\n; (leave these alone: this is only a list of the slicing settings)\n; (overwriting these values will NOT change your printer's behavior)\n; sliced for : {machine_name}\n; jobname : {jobname}\n; gcode generated : {day}, {date}, {time}\n; est. print time : {print_time}\n; nozzle diameter : {machine_nozzle_size}\n; filament diameter : {material_diameter}\n; layer height : {layer_height}\n; 1st layer height : {layer_height_0}\n; line width : {line_width} \n; outer wall wipe dist. : {wall_0_wipe_dist}\n; infill line width : {infill_line_width}\n; wall thickness : {wall_thickness}\n; top thickness : {top_thickness}\n; bottom thickness : {bottom_thickness}\n; infill density : {infill_sparse_density}\n; infill pattern : {infill_pattern}\n; print temperature : {material_print_temperature}\n; 1st layer print temp. : {material_print_temperature_layer_0}\n; heated bed temperature : {material_bed_temperature}\n; 1st layer bed temp. : {material_bed_temperature_layer_0}\n; regular fan speed : {cool_fan_speed_min}\n; max fan speed : {cool_fan_speed_max}\n; retraction amount : {retraction_amount}\n; retr. retract speed : {retraction_retract_speed}\n; retr. prime speed : {retraction_prime_speed}\n; build plate adhesion : {adhesion_type}\n; support ? {support_enable}\n; spiralized ? {magic_spiralize}\n\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Preparing ;write Preparing\nM190 S{material_bed_temperature_layer_0} ;wait for the bed to reach desired temperature\nM109 S180 ;wait for the extruder to reach 180C\nG28 ;home all axes\nM203 Z4 ;slow Z speed down for greater accuracy when probing\nG29 O ;run auto bed leveling procedure IF leveling not active already\n; M500 ;optionally save the mesh\nM203 Z7 ;pick up z speed again for printing\nG28 X ;home x to get as far from the plate as possible\nM420 S1 ;(re) enable bed leveling if turned off by the G28\nG0 Y0 F5000 ;position Y in front\nG0 Z15 F3000 ;position Z\nM109 S{material_print_temperature_layer_0} ;wait for the extruder to reach desired temperature\nM300 S440 P300 ;play a tone\n; M0 Ready! Click to start ; optionally, stop and wait for user to continue\nM420 S1 ;(re) enable bed leveling to make iron-sure\nM117 Print starting ;write Print starting\n;================ ;PRINT:LINE start\nG90 ;absolute positioning\nG92 E0 ;reset the extruder position\nM420 S1 ;(re) enable bed leveling to make iron-sure\nG0 Z0 ;get Z down\nM83 ;relative extrusion mode\nM420 S1 ;(re) enable bed leveling to make iron-sure\nG1 E20 F300 ;extrude __mm of feed stock\nG1 E18 F250 ;extrude __mm of feed stock\nG1 E10 F250 ;extrude __mm of feed stock\nG4 S2 ;pause for ooze\nM400 ;make sure all is finished\nM420 S1 ;(re) enable bed leveling to make iron-sure\nG0 F500 X3 Y0 Z0.3;get to the start of the LINE\nG1 E2 F300 ;extrude __mm of feed stock\nG1 F1000 X152 E7 ;print a thick LINE extruding __mm along the way\nG92 E0 ;reset the extruder position\n;---------------------------------------------\n; ; ; Jellybox Printer Start Script End ; ; ;\n;_____________________________________________\n"
},
"machine_end_gcode": {
- "default_value": "\n;---------------------------------\n;;; Jellybox End Script Begin ;;;\n;_________________________________\nM117 Finishing Up ;write Finishing Up\n\nM104 S0 ;extruder heater off\nM140 S0 ;bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG90 ;absolute positioning\nG28 X ;home x, so the head is out of the way\nG1 Y100 ;move Y forward, so the print is more accessible\nM84 ;steppers off\n\nM117 Print finished ;write Print finished\n;---------------------------------------\n;;; Jellybox End Script End ;;;\n;_______________________________________"
+ "default_value": "\n;---------------------------------\n;;; Jellybox End Script Begin ;;;\n;_________________________________\n; end gcode last modified Nov 30, 2018\nM117 Finishing Up ;write Finishing Up\n\nM107 ;turn the fan off\nM104 S0 ;extruder heater off\nM140 S0 ;bed heater off (if you have it)\nG91 ;relative positioning (includes extruder)\nG1 E-1 F2500 ;retract the filament a bit before lifting the nozzle to release some of the pressure\nG1 Z0.5 E-4 X-10 F9000 ;get out and retract filament even more\nG1 E-25 F2500 ;retract even more\nG90 ;absolute positioning (includes extruder)\nG28 X ;home X so the head is out of the way\nG1 Y140 ;move Y forward, so the print is more accessible\nM84 ;steppers off\n\nM117 Print finished ;write Print finished\n;---------------------------------------\n;;; Jellybox End Script End ;;;\n;_______________________________________"
}
}
}
diff --git a/resources/definitions/imade3d_jellybox_2.def.json b/resources/definitions/imade3d_jellybox_2.def.json
new file mode 100644
index 0000000000..7d7b82e194
--- /dev/null
+++ b/resources/definitions/imade3d_jellybox_2.def.json
@@ -0,0 +1,36 @@
+{
+ "version": 2,
+ "name": "IMADE3D JellyBOX 2",
+ "inherits": "imade3d_jellybox_root",
+ "metadata": {
+ "visible": true,
+ "author": "IMADE3D",
+ "platform": "imade3d_jellybox_2_platform.stl",
+ "platform_offset": [ 0, -10, 0],
+ "preferred_variant_name": "0.4 mm",
+ "preferred_quality_type": "fast",
+ "has_materials": true,
+ "has_variants": true,
+ "has_machine_quality": true,
+ "machine_extruder_trains": {
+ "0": "imade3d_jellybox_2_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "gradual_infill_steps":{"default_value": 0},
+ "gradual_infill_step_height": {"default_value": 3},
+ "machine_head_with_fans_polygon": { "default_value": [[ 0, 0 ],[ 0, 0 ],[ 0, 0 ],[ 0, 0 ]]},
+ "machine_name": { "default_value": "IMADE3D JellyBOX 2" },
+ "machine_width": { "default_value": 180 },
+ "machine_height": { "default_value": 145 },
+ "machine_depth": { "default_value": 165 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "machine_start_gcode": {
+ "default_value": ";---------------------------------------\n; ; ; Jellybox Start Script Begin ; ; ;\n;_______________________________________\n; for slicer: CURA 3\n; start gcode last modified Jun 1, 2019\n\n; Print Settings Summary\n; (leave these alone: this is only a list of the slicing settings)\n; (overwriting these values will NOT change your printer's behavior)\n; sliced for : {machine_name}\n; jobname : {jobname}\n; gcode generated : {day}, {date}, {time}\n; est. print time : {print_time}\n; nozzle diameter : {machine_nozzle_size}\n; filament diameter : {material_diameter}\n; layer height : {layer_height}\n; 1st layer height : {layer_height_0}\n; line width : {line_width} \n; outer wall wipe dist. : {wall_0_wipe_dist}\n; infill line width : {infill_line_width}\n; wall thickness : {wall_thickness}\n; top thickness : {top_thickness}\n; bottom thickness : {bottom_thickness}\n; infill density : {infill_sparse_density}\n; infill pattern : {infill_pattern}\n; print temperature : {material_print_temperature}\n; 1st layer print temp. : {material_print_temperature_layer_0}\n; heated bed temperature : {material_bed_temperature}\n; 1st layer bed temp. : {material_bed_temperature_layer_0}\n; regular fan speed : {cool_fan_speed_min}\n; max fan speed : {cool_fan_speed_max}\n; retraction amount : {retraction_amount}\n; retr. retract speed : {retraction_retract_speed}\n; retr. prime speed : {retraction_prime_speed}\n; build plate adhesion : {adhesion_type}\n; support ? {support_enable}\n; spiralized ? {magic_spiralize}\n\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Preparing ;write Preparing\nM190 S{material_bed_temperature_layer_0} ;wait for the bed to reach desired temperature\nM109 S180 ;wait for the extruder to reach 180C\nG28 ;home all axes\nM203 Z4 ;slow Z speed down for greater accuracy when probing\nG29 O ;run auto bed leveling procedure IF leveling not active already\n; M500 ;optionally save the mesh\nM203 Z7 ;pick up z speed again for printing\nG28 X ;home x to get as far from the plate as possible\nM420 S1 ;(re) enable bed leveling if turned off by the G28\nG0 Y0 F5000 ;position Y in front\nG0 Z15 F3000 ;position Z\nM109 S{material_print_temperature_layer_0} ;wait for the extruder to reach desired temperature\nM300 S440 P300 ;play a tone\n; M0 Ready! Click to start ; optionally, stop and wait for user to continue\nM420 S1 ;(re) enable bed leveling to make iron-sure\nM117 Print starting ;write Print starting\n;================ ;PRINT:LINE start\nG90 ;absolute positioning\nG92 E0 ;reset the extruder position\nM420 S1 ;(re) enable bed leveling to make iron-sure\nG0 Z0 ;get Z down\nM83 ;relative extrusion mode\nM420 S1 ;(re) enable bed leveling to make iron-sure\nG1 E20 F300 ;extrude __mm of feed stock\nG1 E18 F250 ;extrude __mm of feed stock\nG1 E10 F250 ;extrude __mm of feed stock\nG4 S2 ;pause for ooze\nM400 ;make sure all is finished\nM420 S1 ;(re) enable bed leveling to make iron-sure\nG0 F500 X3 Y0 Z0.3;get to the start of the LINE\nG1 E2 F300 ;extrude __mm of feed stock\nG1 F1000 X152 E7 ;print a thick LINE extruding __mm along the way\nG92 E0 ;reset the extruder position\n;---------------------------------------------\n; ; ; Jellybox Printer Start Script End ; ; ;\n;_____________________________________________\n"
+ },
+ "machine_end_gcode": {
+ "default_value": "\n;---------------------------------\n;;; Jellybox End Script Begin ;;;\n;_________________________________\n; end gcode last modified Nov 30, 2018\nM117 Finishing Up ;write Finishing Up\n\nM107 ;turn the fan off\nM104 S0 ;extruder heater off\nM140 S0 ;bed heater off (if you have it)\nG91 ;relative positioning (includes extruder)\nG1 E-1 F2500 ;retract the filament a bit before lifting the nozzle to release some of the pressure\nG1 Z0.5 E-4 X-10 F9000 ;get out and retract filament even more\nG1 E-25 F2500 ;retract even more\nG90 ;absolute positioning (includes extruder)\nG28 X ;home X so the head is out of the way\nG1 Y140 ;move Y forward, so the print is more accessible\nM84 ;steppers off\n\nM117 Print finished ;write Print finished\n;---------------------------------------\n;;; Jellybox End Script End ;;;\n;_______________________________________"
+ }
+ }
+}
diff --git a/resources/definitions/imade3d_jellybox_root.def.json b/resources/definitions/imade3d_jellybox_root.def.json
new file mode 100644
index 0000000000..52f541f1d4
--- /dev/null
+++ b/resources/definitions/imade3d_jellybox_root.def.json
@@ -0,0 +1,143 @@
+{
+ "version": 2,
+ "name": "imade3d_jellybox_root",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "author": "IMADE3D",
+ "manufacturer": "IMADE3D",
+ "category": "Ultimaker",
+ "visible": false,
+ "file_formats": "text/x-gcode",
+ "exclude_materials": [
+ "chromatik_pla",
+ "dsm_arnitel2045_175",
+ "dsm_novamid1070_175",
+ "fabtotum_abs",
+ "fabtotum_nylon",
+ "fabtotum_pla",
+ "fabtotum_tpu",
+ "fiberlogy_hd_pla",
+ "filo3d_pla_green",
+ "filo3d_pla_red",
+ "filo3d_pla",
+ "generic_abs_175",
+ "generic_abs",
+ "generic_bam",
+ "generic_cpe_175",
+ "generic_cpe_plus",
+ "generic_cpe",
+ "generic_hips_175",
+ "generic_hips",
+ "generic_nylon_175",
+ "generic_nylon",
+ "generic_pc_175",
+ "generic_pc",
+ "generic_petg",
+ "generic_petg_175",
+ "generic_pla",
+ "generic_pla_175",
+ "generic_pp",
+ "generic_pva_175",
+ "generic_pva",
+ "generic_tough_pla",
+ "generic_tpu",
+ "imade3d_petg_green",
+ "imade3d_petg_pink",
+ "imade3d_pla_green",
+ "imade3d_pla_pink",
+ "innofill_innoflex60_175",
+ "octofiber_pla",
+ "polyflex_pla",
+ "polymax_pla",
+ "polyplus_pla",
+ "polywood_pla",
+ "tizyx_abs",
+ "tizyx_pla_bois",
+ "tizyx_pla",
+ "ultimaker_abs_black",
+ "ultimaker_abs_blue",
+ "ultimaker_abs_green",
+ "ultimaker_abs_grey",
+ "ultimaker_abs_orange",
+ "ultimaker_abs_pearl-gold",
+ "ultimaker_abs_red",
+ "ultimaker_abs_silver-metallic",
+ "ultimaker_abs_white",
+ "ultimaker_abs_yellow",
+ "ultimaker_bam",
+ "ultimaker_cpe_black",
+ "ultimaker_cpe_blue",
+ "ultimaker_cpe_dark-grey",
+ "ultimaker_cpe_green",
+ "ultimaker_cpe_light-grey",
+ "ultimaker_cpe_plus_black",
+ "ultimaker_cpe_plus_transparent",
+ "ultimaker_cpe_plus_white",
+ "ultimaker_cpe_red",
+ "ultimaker_cpe_transparent",
+ "ultimaker_cpe_white",
+ "ultimaker_cpe_yellow",
+ "ultimaker_nylon_black",
+ "ultimaker_nylon_transparent",
+ "ultimaker_pc_black",
+ "ultimaker_pc_transparent",
+ "ultimaker_pc_white",
+ "ultimaker_pla_black",
+ "ultimaker_pla_blue",
+ "ultimaker_pla_green",
+ "ultimaker_pla_magenta",
+ "ultimaker_pla_orange",
+ "ultimaker_pla_pearl-white",
+ "ultimaker_pla_red",
+ "ultimaker_pla_silver-metallic",
+ "ultimaker_pla_transparent",
+ "ultimaker_pla_white",
+ "ultimaker_pla_yellow",
+ "ultimaker_pp_transparent",
+ "ultimaker_pva",
+ "ultimaker_tough_pla_black",
+ "ultimaker_tough_pla_green",
+ "ultimaker_tough_pla_red",
+ "ultimaker_tough_pla_white",
+ "ultimaker_tpu_black",
+ "ultimaker_tpu_blue",
+ "ultimaker_tpu_red",
+ "ultimaker_tpu_white",
+ "verbatim_bvoh_175",
+ "Vertex_Delta_ABS",
+ "Vertex_Delta_PET",
+ "Vertex_Delta_PLA",
+ "Vertex_Delta_TPU",
+ "zyyx_pro_flex",
+ "zyyx_pro_pla"
+ ]
+ },
+ "overrides": {
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "material_print_temperature": {
+ "minimum_value": "0"
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "material_bed_temperature": {
+ "minimum_value": "0"
+ },
+ "material_standby_temperature": {
+ "minimum_value": "0"
+ },
+ "relative_extrusion":
+ {
+ "value": true,
+ "enabled": true
+ }
+ }
+}
diff --git a/resources/definitions/innovo_inventor.def.json b/resources/definitions/innovo_inventor.def.json
index 91a6d8365b..df839b0fe4 100644
--- a/resources/definitions/innovo_inventor.def.json
+++ b/resources/definitions/innovo_inventor.def.json
@@ -32,7 +32,7 @@
"machine_center_is_zero": {
"default_value": true
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
[-43.7, -19.2],
[-43.7, 55],
@@ -41,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": 82.3
+ "value": "82.3"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -61,36 +61,10 @@
"top_bottom_thickness": {
"default_value": 1.2
},
- "material_print_temperature": {
- "default_value": 205
- },
- "material_bed_temperature": {
- "default_value": 60
- },
"speed_print": {
"default_value": 50
},
- "speed_wall_0": {
- "default_value": 25
- },
- "speed_wall_x": {
- "default_value": 40
- },
- "speed_infill": {
- "default_value": 80
- },
- "speed_topbottom": {
- "default_value": 30
- },
- "speed_support_interface":
- {
- "default_value": 20
- },
- "speed_travel": {
- "default_value": 150
- },
"speed_layer_0": {
- "default_value": 30.0,
"minimum_value": 0.1
}
}
diff --git a/resources/definitions/jgaurora_a1.def.json b/resources/definitions/jgaurora_a1.def.json
index b9a921c311..1c910f0d95 100644
--- a/resources/definitions/jgaurora_a1.def.json
+++ b/resources/definitions/jgaurora_a1.def.json
@@ -39,7 +39,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 10
+ "value": "10"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -47,12 +47,6 @@
"material_diameter": {
"default_value": 1.75
},
- "material_print_temperature": {
- "default_value": 215
- },
- "material_bed_temperature": {
- "default_value": 67
- },
"layer_height_0": {
"default_value": 0.12
},
@@ -62,21 +56,6 @@
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 12
- },
"support_enable": {
"default_value": true
},
diff --git a/resources/definitions/jgaurora_a3s.def.json b/resources/definitions/jgaurora_a3s.def.json
new file mode 100644
index 0000000000..ead0a5f9e7
--- /dev/null
+++ b/resources/definitions/jgaurora_a3s.def.json
@@ -0,0 +1,72 @@
+{
+ "name": "JGAurora A3S",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Samuel Pinches",
+ "manufacturer": "JGAurora",
+ "file_formats": "text/x-gcode",
+ "preferred_quality_type": "normal",
+ "machine_extruder_trains":
+ {
+ "0": "jgaurora_a3s_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "JGAurora A3S"
+ },
+ "machine_start_gcode": {
+ "default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 ;home all axis\nG92 E0 ;zero the extruded length\nG1 Z1 F1000 ;move up slightly\nG1 X60.0 Z0 E9.0 F1000.0;intro line\nG1 X100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\n; -- end of START GCODE --"
+ },
+ "machine_end_gcode": {
+ "default_value": "; -- END GCODE --\nM104 S0 ;turn off nozzle heater\nM140 S0 ;turn off bed heater\nG91 ;set to relative positioning\nG1 E-10 F300 ;retract the filament slightly\nG90 ;set to absolute positioning\nG28 X0 ;move to the X-axis origin (Home)\nG0 Y200 F600 ;bring the bed to the front for easy print removal\nM84 ;turn off stepper motors\n; -- end of END GCODE --"
+ },
+ "machine_width": {
+ "default_value": 205
+ },
+ "machine_height": {
+ "default_value": 205
+ },
+ "machine_depth": {
+ "default_value": 205
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "gantry_height": {
+ "value": "10"
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "layer_height_0": {
+ "default_value": 0.12
+ },
+ "wall_thickness": {
+ "default_value": 1.2
+ },
+ "speed_print": {
+ "default_value": 35
+ },
+ "support_enable": {
+ "default_value": true
+ },
+ "retraction_enable": {
+ "default_value": true
+ },
+ "retraction_amount": {
+ "default_value": 8
+ },
+ "retraction_speed": {
+ "default_value": 45
+ }
+ }
+}
diff --git a/resources/definitions/jgaurora_a5.def.json b/resources/definitions/jgaurora_a5.def.json
index d84a8440e6..b9f179d38e 100644
--- a/resources/definitions/jgaurora_a5.def.json
+++ b/resources/definitions/jgaurora_a5.def.json
@@ -41,7 +41,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 10
+ "value": "10"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -49,12 +49,6 @@
"material_diameter": {
"default_value": 1.75
},
- "material_print_temperature": {
- "default_value": 215
- },
- "material_bed_temperature": {
- "default_value": 67
- },
"layer_height_0": {
"default_value": 0.12
},
@@ -64,21 +58,6 @@
"speed_print": {
"default_value": 40
},
- "speed_infill": {
- "default_value": 40
- },
- "speed_wall": {
- "default_value": 35
- },
- "speed_topbottom": {
- "default_value": 35
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 12
- },
"support_enable": {
"default_value": true
},
diff --git a/resources/definitions/jgaurora_jgmaker_magic.def.json b/resources/definitions/jgaurora_jgmaker_magic.def.json
new file mode 100644
index 0000000000..8d0349a48c
--- /dev/null
+++ b/resources/definitions/jgaurora_jgmaker_magic.def.json
@@ -0,0 +1,72 @@
+{
+ "name": "JGAurora JGMaker Magic",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Samuel Pinches",
+ "manufacturer": "JGAurora",
+ "file_formats": "text/x-gcode",
+ "preferred_quality_type": "fast",
+ "machine_extruder_trains":
+ {
+ "0": "jgaurora_jgmaker_magic_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "JGAurora JGMaker Magic"
+ },
+ "machine_start_gcode": {
+ "default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 ;home all axis\nM420 S1 ;turn on mesh bed levelling if enabled in firmware\nG92 E0 ;zero the extruded length\nG1 Z1 F1000 ;move up slightly\nG1 X60.0 Z0 E9.0 F1000.0;intro line\nG1 X100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\n; -- end of START GCODE --"
+ },
+ "machine_end_gcode": {
+ "default_value": "; -- END GCODE --\nM104 S0 ;turn off nozzle heater\nM140 S0 ;turn off bed heater\nG91 ;set to relative positioning\nG1 E-10 F300 ;retract the filament slightly\nG90 ;set to absolute positioning\nG28 X0 ;move to the X-axis origin (Home)\nG0 Y280 F600 ;bring the bed to the front for easy print removal\nM84 ;turn off stepper motors\n; -- end of END GCODE --"
+ },
+ "machine_width": {
+ "default_value": 220
+ },
+ "machine_height": {
+ "default_value": 250
+ },
+ "machine_depth": {
+ "default_value": 220
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "gantry_height": {
+ "value": "10"
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "layer_height_0": {
+ "default_value": 0.2
+ },
+ "wall_thickness": {
+ "default_value": 1.2
+ },
+ "speed_print": {
+ "default_value": 60
+ },
+ "support_enable": {
+ "default_value": true
+ },
+ "retraction_enable": {
+ "default_value": true
+ },
+ "retraction_amount": {
+ "default_value": 5
+ },
+ "retraction_speed": {
+ "default_value": 50
+ }
+ }
+}
diff --git a/resources/definitions/jgaurora_z_603s.def.json b/resources/definitions/jgaurora_z_603s.def.json
index 3a78585240..8dbf5a82bb 100644
--- a/resources/definitions/jgaurora_z_603s.def.json
+++ b/resources/definitions/jgaurora_z_603s.def.json
@@ -21,8 +21,8 @@
"default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 ;home all axis\nM420 S1 ;turn on mesh bed levelling if enabled in firmware\nG92 E0 ;zero the extruded length\nG1 Z1 F1000 ;move up slightly\nG1 X60.0 Z0 E9.0 F1000.0;intro line\nG1 X100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\n; -- end of START GCODE --"
},
"machine_end_gcode": {
- "default_value": "; -- END GCODE --\nM104 S0 ;turn off nozzle heater\nM140 S0 ;turn off bed heater\nG91 ;set to relative positioning\nG1 E-10 F300 ;retract the filament slightly\nG90 ;set to absolute positioning\nG28 X0 ;move to the X-axis origin (Home)\nG0 Y280 F600 ;bring the bed to the front for easy print removal\nM84 ;turn off stepper motors\n; -- end of END GCODE --"
- },
+ "default_value": "; -- END GCODE --\nM104 S0 ;turn off nozzle heater\nM140 S0 ;turn off bed heater\nG91 ;set to relative positioning\nG1 E-10 F300 ;retract the filament slightly\nG90 ;set to absolute positioning\nG28 X0 Y0 F600 ;move to the X/Y-axis origin (Home)\nM84 ;turn off stepper motors\n; -- end of END GCODE --"
+ },
"machine_width": {
"default_value": 280
},
@@ -39,7 +39,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 10
+ "value": "10"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -47,12 +47,6 @@
"material_diameter": {
"default_value": 1.75
},
- "material_print_temperature": {
- "default_value": 210
- },
- "material_bed_temperature": {
- "default_value": 55
- },
"layer_height_0": {
"default_value": 0.2
},
@@ -62,21 +56,6 @@
"speed_print": {
"default_value": 60
},
- "speed_infill": {
- "default_value": 60
- },
- "speed_wall": {
- "default_value": 30
- },
- "speed_topbottom": {
- "default_value": 45
- },
- "speed_travel": {
- "default_value": 125
- },
- "speed_layer_0": {
- "default_value": 20
- },
"support_enable": {
"default_value": true
},
diff --git a/resources/definitions/julia.def.json b/resources/definitions/julia.def.json
index 62e4170c1f..15e5057a55 100644
--- a/resources/definitions/julia.def.json
+++ b/resources/definitions/julia.def.json
@@ -21,25 +21,14 @@
"machine_end_gcode": {
"default_value": " M104 S0 ;extruder heater off\n M140 S0 ;heated bed heater off (if you have it)\n G91 ;relative positioning\n G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n G1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\n G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\n M84 ;steppers off\n G90 ;absolute positioning\n"
},
- "material_bed_temperature": { "default_value": 100 },
"layer_height": { "default_value": 0.2 },
"support_angle": { "default_value": 30 },
- "infill_overlap": { "default_value": 30 },
"layer_height_0": { "default_value": 0.2 },
"speed_print": { "default_value": 80 },
- "speed_wall_0": { "default_value": 30 },
- "speed_travel": { "default_value": 150 },
- "brim_line_count": { "default_value": 15 },
- "skin_overlap": { "default_value": 30 },
"prime_tower_size": { "default_value": 8.660254037844387 },
- "bottom_thickness": { "default_value": 0.8 },
"retraction_amount": { "default_value": 3 },
- "speed_topbottom": { "default_value": 80 },
- "material_print_temperature": { "default_value": 230 },
"support_pattern": { "default_value": "grid" },
- "speed_infill": { "default_value": 80 },
"infill_sparse_density": { "default_value": 10 },
- "top_thickness": { "default_value": 0.8 },
"machine_extruder_count": { "default_value": 1 },
"retraction_combing": { "default_value": "off" },
"machine_heated_bed": { "default_value": true },
diff --git a/resources/definitions/kemiq_q2_beta.def.json b/resources/definitions/kemiq_q2_beta.def.json
index 387818565e..f0ae009419 100644
--- a/resources/definitions/kemiq_q2_beta.def.json
+++ b/resources/definitions/kemiq_q2_beta.def.json
@@ -41,7 +41,7 @@
"default_value": 2
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/kemiq_q2_gama.def.json b/resources/definitions/kemiq_q2_gama.def.json
index fd6f2d54aa..07ff6dcbf7 100644
--- a/resources/definitions/kemiq_q2_gama.def.json
+++ b/resources/definitions/kemiq_q2_gama.def.json
@@ -42,7 +42,7 @@
"default_value": 2
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/key3d_tyro.def.json b/resources/definitions/key3d_tyro.def.json
new file mode 100644
index 0000000000..0bfc78c115
--- /dev/null
+++ b/resources/definitions/key3d_tyro.def.json
@@ -0,0 +1,65 @@
+{
+ "name": "Tyro",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "DragonJe",
+ "manufacturer": "Key3D",
+ "file_formats": "text/x-gcode",
+ "platform_offset": [0, 0, 0],
+ "has_materials": true,
+ "has_variants": false,
+ "preferred_quality_type": "normal",
+ "has_machine_quality": true,
+ "preferred_material": "generic_pla",
+ "machine_extruder_trains":
+ {
+ "0": "key3d_tyro_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": {
+ "default_value": "Tyro"
+ },
+ "machine_width": {
+ "default_value": 150
+ },
+ "machine_height": {
+ "default_value": 150
+ },
+ "machine_depth": {
+ "default_value": 150
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-30, 34],
+ [-30, -32],
+ [30, -32],
+ [30, 34]
+ ]
+ },
+ "gantry_height": {
+ "value": "30"
+ },
+ "machine_heated_bed": {
+ "default_value": false
+ },
+ "machine_heated_build_volume": {
+ "default_value": false
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "G28 ; Home\nG1 Z15.0 F6000 ; Move Z axis up 15mm\n ; Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0"
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0\nM140 S0\n ; Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"
+ }
+ }
+}
diff --git a/resources/definitions/kossel_mini.def.json b/resources/definitions/kossel_mini.def.json
index 91f374fb6d..d9c3b3d37f 100644
--- a/resources/definitions/kossel_mini.def.json
+++ b/resources/definitions/kossel_mini.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Claudio Sampaio (Patola)",
- "manufacturer": "Other",
+ "manufacturer": "Johann",
"file_formats": "text/x-gcode",
"platform": "kossel_platform.stl",
"platform_offset": [0, -0.25, 0],
diff --git a/resources/definitions/kossel_pro.def.json b/resources/definitions/kossel_pro.def.json
index e104538b2c..f26c6ed068 100644
--- a/resources/definitions/kossel_pro.def.json
+++ b/resources/definitions/kossel_pro.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Chris Petersen",
- "manufacturer": "OpenBeam",
+ "manufacturer": "Johann",
"file_formats": "text/x-gcode",
"platform": "kossel_pro_build_platform.stl",
"platform_offset": [0, -0.25, 0],
diff --git a/resources/definitions/kupido.def.json b/resources/definitions/kupido.def.json
index 412fe979b8..ad0182a5f6 100644
--- a/resources/definitions/kupido.def.json
+++ b/resources/definitions/kupido.def.json
@@ -1,13 +1,21 @@
{
- "name": "Kupido",
"version": 2,
+ "name": "KUPIDO",
"inherits": "fdmprinter",
- "metadata": {
+ "metadata":
+ {
"visible": true,
- "author": "Ultimaker",
- "manufacturer": "Kupido",
+ "author": "ALYA",
+ "manufacturer": "Kati Hal ARGE",
+ "category": "Other",
"file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0],
+ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "generic_tpu_175", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla","tizyx_pla","tizyx_abs","tizyx_pla_bois" ],
+ "preferred_material": "generic_pla",
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variants": false,
+ "supports_usb_connection": false,
"machine_extruder_trains":
{
"0": "kupido_extruder_0"
@@ -15,26 +23,27 @@
},
"overrides": {
- "machine_name": { "default_value": "Kupido" },
- "machine_start_gcode": {
- "default_value": " ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {infill_sparse_density}\n ;M190 S{material_bed_temperature} ;Uncomment to add your own bed temperature line\n ;M109 S{material_print_temperature} ;Uncomment to add your own temperature line\n G21 ;metric values\n G90 ;absolute positioning\n M82 ;set extruder to absolute mode\n M107 ;start with the fan off\n G28 X0 Y0 ;move X Y to endstops\n G28 Z0 ;move Z to endstops\n G1 Z20.0 F40 ;move the platform down 20mm\n G1 Y0 X170 F{speed_travel}\n G92 E0 ;zero the extruded length\n G1 F200 E10 ;extrude 3mm of feed stock\n G92 E0 ;zero the extruded length again\n G4 P7000\n G1 F{speed_travel}\n ;Put printing message on LCD screen\n M117 Printing...\n"
+ "machine_name": { "default_value": "KUPIDO" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 195 },
+ "machine_height": { "default_value": 190 },
+ "machine_depth": { "default_value": 195 },
+ "machine_center_is_zero": { "default_value": false },
+ "gantry_height": { "value": "55" },
+ "retraction_amount": { "default_value": 1 },
+ "support_enable": { "default_value": true},
+ "machine_head_with_fans_polygon": {
+ "default_value": [[75, 18],[18, 18],[18, 35],[75, 35]]
},
- "machine_end_gcode": {
- "default_value": " M104 S0 ;extruder heater off\n M140 S0 ;heated bed heater off (if you have it)\n G91 ;relative positioning\n G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n G1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\n G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\n M84 ;steppers off\n G90 ;absolute positioning\n"
+ "adhesion_type": {"options": {"raft": "Raft" ,"none": "None", "brim": "Brim"}, "default_value": "raft"},
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode":
+ {
+ "default_value": ";Sliced at: {day} {date} {time} \n ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} \n ;Print time: {print_time} \n ;Filament used: {filament_amount}m {filament_weight}g \n ;Filament cost: {filament_cost} \n G28 X0 Y0 ;move X Y to endstops \n G28 Z0 ;move Z to endstops \n M190 S{material_bed_temperature} ;bed temp \n M107 ; switch fan off \n M109 S{material_print_temperature} ;extruder temp set \n G1 F3000 \n G1 Z10 \n G92 E0 ;zero the extruded length \n G1 F200 E1 ;extrude 1mm of feed stock \n G92 E0 ;zero the extruded length again \n G4 P7000 ; wait 7000ms \n M117 Printing... ;Put printing message on LCD screen"
},
- "prime_tower_size": { "default_value": 8.660254037844387 },
- "retraction_speed": { "default_value": 60 },
- "material_bed_temperature": { "default_value": 60 },
- "speed_wall_x": { "default_value": 40 },
- "skirt_line_count": { "default_value": 2 },
- "retraction_min_travel": { "default_value": 2 },
- "speed_wall_0": { "default_value": 30 },
- "material_print_temperature": { "default_value": 220 },
- "brim_line_count": { "default_value": 15 },
- "retraction_amount": { "default_value": 3.6 },
- "speed_topbottom": { "default_value": 20 },
- "layer_height": { "default_value": 0.2 },
- "speed_print": { "default_value": 30 },
- "speed_infill": { "default_value": 30 }
+ "machine_end_gcode":
+ {
+ "default_value": ";End GCode\nM104 S0 ;extruder heater off \nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG28 Z0\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
+ }
}
-}
+}
\ No newline at end of file
diff --git a/resources/definitions/leapfrog_bolt_pro.def.json b/resources/definitions/leapfrog_bolt_pro.def.json
new file mode 100644
index 0000000000..09b9ecded5
--- /dev/null
+++ b/resources/definitions/leapfrog_bolt_pro.def.json
@@ -0,0 +1,115 @@
+{
+ "version": 2,
+ "name": "Leapfrog Bolt Pro",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Karan and Vincent 20191104",
+ "manufacturer": "Leapfrog B.V.",
+ "category": "Other",
+ "platform": "leapfrog_bolt_pro_platform.stl",
+ "platform_offset": [0, 0, -14],
+ "file_formats": "text/x-gcode",
+ "supports_usb_connection": false,
+ "supports_network_connection": false,
+ "has_materials": true,
+ "has_machine_quality": true,
+ "has_variants": true,
+ "preferred_variant_name": "Brass 0.4",
+ "preferred_material": "leapfrog_epla_natural",
+ "variants_name": "Hot end",
+ "exclude_materials": [
+ "generic_pla_175",
+ "generic_abs_175",
+ "generic_cpe_175",
+ "generic_hips_175",
+ "generic_nylon_175",
+ "generic_pc_175",
+ "generic_petg_175",
+ "generic_pva_175",
+ "generic_tpu_175",
+ "chromatik_pla",
+ "dsm_arnitel2045_175",
+ "dsm_novamid1070_175",
+ "emotiontech_abs",
+ "emotiontech_petg",
+ "emotiontech_pla",
+ "emotiontech_pva-m",
+ "emotiontech_pva-oks",
+ "emotiontech_pva-s",
+ "emotiontech_tpu98a",
+ "fabtotum_abs",
+ "fabtotum_nylon",
+ "fabtotum_pla",
+ "fabtotum_tpu",
+ "fiberlogy_hd_pla",
+ "filo3d_pla",
+ "filo3d_pla_green",
+ "filo3d_pla_red",
+ "imade3d_petg_175",
+ "imade3d_pla_175",
+ "innofill_innoflex60_175",
+ "octofiber_pla",
+ "polyflex_pla",
+ "polymax_pla",
+ "polyplus_pla",
+ "polywood_pla",
+ "tizyx_abs",
+ "tizyx_pla",
+ "tizyx_flex",
+ "tizyx_petg",
+ "tizyx_pva",
+ "tizyx_pla_bois",
+ "verbatim_bvoh_175",
+ "Vertex_Delta_ABS",
+ "Vertex_Delta_PET",
+ "Vertex_Delta_PLA_Glitter",
+ "Vertex_Delta_PLA_Mat",
+ "Vertex_Delta_PLA_Satin",
+ "Vertex_Delta_PLA_Wood",
+ "Vertex_Delta_PLA",
+ "Vertex_Delta_TPU",
+ "zyyx_pro_flex",
+ "zyyx_pro_pla"
+ ],
+ "machine_extruder_trains":
+ {
+ "0": "leapfrog_bolt_pro_extruder_right",
+ "1": "leapfrog_bolt_pro_extruder_left"
+ }
+ },
+ "overrides": {
+ "machine_name": {"default_value": "Leapfrog Bolt Pro" },
+ "machine_extruder_count": {"default_value": 2},
+ "machine_center_is_zero": {"default_value": false},
+ "machine_width": {"default_value": 302},
+ "machine_height": {"default_value": 205},
+ "machine_depth": {"default_value": 322},
+ "machine_heated_bed": {"default_value": true},
+ "machine_head_with_fans_polygon": {"default_value": [[-60, 110 ], [-60, -45], [60, -45 ], [60, 110]]},
+ "machine_max_feedrate_z": {"default_value": 16.7 },
+ "machine_max_feedrate_e": {"default_value": 50 },
+ "machine_max_acceleration_z": {"default_value": 100 },
+ "machine_acceleration": {"default_value": 400 },
+ "machine_max_jerk_xy": {"default_value": 20 },
+ "machine_max_jerk_z": {"default_value": 0.4 },
+ "machine_max_jerk_e": {"default_value": 5 },
+ "machine_gcode_flavor": {"default_value": "RepRap (Marlin/Sprinter)"},
+ "material_final_print_temperature": {"value": "default_material_print_temperature" },
+ "material_initial_print_temperature": {"value": "default_material_print_temperature" },
+ "gantry_height": {"value": "20"},
+ "retraction_combing": { "default_value": "all" },
+ "retraction_amount": {"default_value": 2},
+ "adhesion_type": {"default_value": "skirt"},
+ "skirt_line_count": {"default_value": 3},
+ "machine_use_extruder_offset_to_offset_coords": {"default_value": true},
+ "machine_start_gcode": {"default_value": "G90\nG28 X0 Y0 Z0\nG1 Z5 F1000\nG92 E0\nG1 Y-32 F12000\nG1 E15 F1000\nG1 E45 F150\nG4 S5"},
+ "machine_end_gcode": {"default_value": "G92 E0\nG1 E-3 F300\nM104 S0 T0\nM104 S0 T1\nM140 S0\nG28 X0 Y0\nM84"},
+ "prime_tower_enable": { "resolve": "extruders_enabled_count > 1"},
+ "prime_tower_position_x": {"value": "169" },
+ "prime_tower_position_y": {"value": "25" },
+ "speed_travel": { "value": "200" },
+ "build_volume_temperature": {"enabled": false},
+ "material_standby_temperature": {"enabled": false }
+ }
+}
diff --git a/resources/definitions/makeR_pegasus.def.json b/resources/definitions/makeR_pegasus.def.json
index ac09aa01ac..63f76194a4 100644
--- a/resources/definitions/makeR_pegasus.def.json
+++ b/resources/definitions/makeR_pegasus.def.json
@@ -32,7 +32,7 @@
"machine_center_is_zero": {
"default_value": false
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
[-75, -18],
[-75, 35],
@@ -41,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": -25
+ "value": "25"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/makeR_prusa_tairona_i3.def.json b/resources/definitions/makeR_prusa_tairona_i3.def.json
index 0e59874978..3c57c0cbc8 100644
--- a/resources/definitions/makeR_prusa_tairona_i3.def.json
+++ b/resources/definitions/makeR_prusa_tairona_i3.def.json
@@ -32,7 +32,7 @@
"machine_center_is_zero": {
"default_value": false
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
[-75, -18],
[-75, 35],
@@ -41,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/makeblock_mcreate.def.json b/resources/definitions/makeblock_mcreate.def.json
new file mode 100644
index 0000000000..7a2d575395
--- /dev/null
+++ b/resources/definitions/makeblock_mcreate.def.json
@@ -0,0 +1,68 @@
+{
+ "version": 2,
+ "name": "Makeblock mCreate",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "author": "Makeblock",
+ "manufacturer": "Makeblock",
+ "visible": true,
+ "file_formats": "application/gzip;text/x-gcode",
+ "has_machine_quality": true,
+ "preferred_quality_type": "normal",
+ "machine_extruder_trains": {
+ "0": "makeblock_mcreate_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Makeblock mCreate"
+ },
+ "machine_width": {
+ "default_value": 225
+ },
+ "machine_depth": {
+ "default_value": 225
+ },
+ "machine_height": {
+ "default_value": 300
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ "machine_gcode_flavor": {
+ "default_value": "Marlin"
+ },
+ "gantry_height": {
+ "value": 15.0
+ },
+ "machine_extruder_count": {
+ "default_value": 1
+ },
+ "machine_start_gcode": {
+ "default_value": "; Mcreate Start Gcode \nG28 ; Home all axes \nG92 E0 ; Reset Extruder\nG1 X0 Y0 Z15 F3000.0 ; Move to start position \nG1 E10 F400 ;load filament \nG1 E2 F400 ;retarct filament \nG92 E0 ; Reset Extruder \nG1 X0 Y130 Z15 F3000.0 \nG12 ; clean nozzle \nG1 X0 Y0 Z0.3 F3000.0 ; Move to start position \nG1 E9.0 F400 ;loadsome filament \nG92 E0 ; Reset Extruder \n; End of start GCode"
+ },
+ "machine_end_gcode": {
+ "default_value": "; Mcreate end Gcode \nG4 ; Wait command in buffer have finished \nG92 E0 \nG1 E-2 F300; retract filament \nG28 X Z; home x z axis \nG1 F3000 Y220;Move Heat Bed to the front for easy print removal \nM104 S0; Turn off the nozzle heat \nM140 S0; Turn off the bed heat \nM107 ; Turn off the Fan \nM84 ; Disable stepper motors \n; End of GCode"
+ }
+ }
+}
diff --git a/resources/definitions/makeit_pro_l.def.json b/resources/definitions/makeit_pro_l.def.json
index d40d63f97b..d601a5c309 100644
--- a/resources/definitions/makeit_pro_l.def.json
+++ b/resources/definitions/makeit_pro_l.def.json
@@ -4,8 +4,8 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "author": "NA",
- "manufacturer": "NA",
+ "author": "unknown",
+ "manufacturer": "MAKEiT 3D",
"file_formats": "text/x-gcode",
"has_materials": false,
"machine_extruder_trains":
@@ -39,7 +39,7 @@
]
},
"gantry_height": {
- "default_value": 330
+ "value": "330"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -77,27 +77,12 @@
"retraction_amount": {
"default_value": 6
},
- "retraction_min_travel": {
- "default_value": 1.5
- },
- "speed_travel": {
- "default_value": 150
- },
"speed_print": {
"default_value": 60
},
"wall_thickness": {
"default_value": 1.2
},
- "bottom_thickness": {
- "default_value": 0.2
- },
- "speed_layer_0": {
- "default_value": 20
- },
- "speed_print_layer_0": {
- "default_value": 20
- },
"cool_min_layer_time_fan_speed_max": {
"default_value": 5
},
diff --git a/resources/definitions/makeit_pro_m.def.json b/resources/definitions/makeit_pro_m.def.json
index 1f0381df86..267646b647 100644
--- a/resources/definitions/makeit_pro_m.def.json
+++ b/resources/definitions/makeit_pro_m.def.json
@@ -4,8 +4,8 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "author": "NA",
- "manufacturer": "NA",
+ "author": "unknown",
+ "manufacturer": "MAKEiT 3D",
"file_formats": "text/x-gcode",
"has_materials": false,
"machine_extruder_trains":
@@ -39,7 +39,7 @@
]
},
"gantry_height": {
- "default_value": 200
+ "value": "200"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -77,27 +77,12 @@
"retraction_amount": {
"default_value": 6
},
- "retraction_min_travel": {
- "default_value": 1.5
- },
- "speed_travel": {
- "default_value": 150
- },
"speed_print": {
"default_value": 60
},
"wall_thickness": {
"default_value": 1.2
},
- "bottom_thickness": {
- "default_value": 0.2
- },
- "speed_layer_0": {
- "default_value": 20
- },
- "speed_print_layer_0": {
- "default_value": 20
- },
"cool_min_layer_time_fan_speed_max": {
"default_value": 5
},
diff --git a/resources/definitions/maker_starter.def.json b/resources/definitions/maker_starter.def.json
index be85e54967..96dca118af 100644
--- a/resources/definitions/maker_starter.def.json
+++ b/resources/definitions/maker_starter.def.json
@@ -33,7 +33,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -53,57 +53,15 @@
"layer_height_0": {
"default_value": 0.2
},
- "wall_line_count": {
- "default_value": 2
- },
- "top_layers": {
- "default_value": 4
- },
- "bottom_layers": {
- "default_value": 4
- },
"speed_print": {
"default_value": 50
},
- "speed_wall": {
- "default_value": 30
- },
- "speed_wall_0": {
- "default_value": 30
- },
- "speed_wall_x": {
- "default_value": 30
- },
- "speed_topbottom": {
- "default_value": 50
- },
- "speed_support": {
- "default_value": 50
- },
- "speed_travel": {
- "default_value": 120
- },
- "speed_layer_0": {
- "default_value": 20
- },
- "skirt_brim_speed": {
- "default_value": 15
- },
"speed_slowdown_layers": {
"default_value": 4
},
"infill_sparse_density": {
"default_value": 20
},
- "cool_fan_speed_min": {
- "default_value": 50
- },
- "cool_fan_speed_max": {
- "default_value": 100
- },
- "cool_fan_full_layer": {
- "default_value": 4
- },
"cool_min_layer_time": {
"default_value": 5
},
@@ -122,17 +80,11 @@
"support_z_distance": {
"default_value": 0.2
},
- "support_top_distance": {
- "default_value": 0.2
- },
- "support_bottom_distance": {
- "default_value": 0.24
- },
"support_pattern": {
"default_value": "ZigZag"
},
"support_infill_rate": {
- "default_value": 15
+ "value": "15 if support_enable else 0 if support_tree_enable else 15"
},
"adhesion_type": {
"default_value": "raft"
@@ -140,24 +92,6 @@
"skirt_brim_minimal_length": {
"default_value": 100
},
- "raft_base_line_spacing": {
- "default_value": 2
- },
- "raft_base_thickness": {
- "default_value": 0.3
- },
- "raft_base_line_width": {
- "default_value": 2
- },
- "raft_base_speed": {
- "default_value": 15
- },
- "raft_interface_thickness": {
- "default_value": 0.24
- },
- "raft_interface_line_width": {
- "default_value": 0.6
- },
"raft_airgap": {
"default_value": 0.2
},
diff --git a/resources/definitions/makerbotreplicator.def.json b/resources/definitions/makerbotreplicator.def.json
index 3b02215e74..24b556e1ee 100644
--- a/resources/definitions/makerbotreplicator.def.json
+++ b/resources/definitions/makerbotreplicator.def.json
@@ -18,9 +18,7 @@
"overrides": {
"prime_tower_size": { "default_value": 10.0 },
"infill_sparse_density": { "default_value": 10 },
- "speed_travel": { "default_value": 150 },
"layer_height": { "default_value": 0.15 },
- "material_print_temperature": { "default_value": 220 },
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/malyan_m180.def.json b/resources/definitions/malyan_m180.def.json
index 53864dabae..bb812b6dd6 100644
--- a/resources/definitions/malyan_m180.def.json
+++ b/resources/definitions/malyan_m180.def.json
@@ -1,5 +1,4 @@
{
- "id": "malyan_m180",
"version": 2,
"name": "Malyan M180",
"inherits": "fdmprinter",
@@ -53,7 +52,7 @@
"default_value": 92
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json
index f2c01b3831..fc8756ff6a 100644
--- a/resources/definitions/malyan_m200.def.json
+++ b/resources/definitions/malyan_m200.def.json
@@ -1,5 +1,4 @@
{
- "id": "malyan_m200",
"version": 2,
"name": "Malyan M200",
"inherits": "fdmprinter",
@@ -30,8 +29,6 @@
"speed_wall_x": { "value": "speed_print" },
"speed_support": { "value": "speed_wall_0" },
"speed_layer_0": { "value": "round(speed_print / 2.0, 2)" },
- "speed_travel": { "default_value": 50 },
- "speed_travel_layer_0": { "default_value": 40 },
"speed_infill": { "value": "speed_print" },
"speed_topbottom": {"value": "speed_print / 2"},
@@ -80,7 +77,6 @@
"raft_surface_layers": { "default_value": 1 },
"skirt_line_count": { "default_value": 2},
"brim_width" : { "default_value": 5},
- "start_layers_at_same_position": { "default_value": true},
"retraction_combing": { "default_value": "noskin" },
"retraction_amount" : { "default_value": 4.5},
"retraction_speed" : { "default_value": 40},
diff --git a/resources/definitions/mankati_fullscale_xt_plus.def.json b/resources/definitions/mankati_fullscale_xt_plus.def.json
index 507e5209b2..b6fa040750 100644
--- a/resources/definitions/mankati_fullscale_xt_plus.def.json
+++ b/resources/definitions/mankati_fullscale_xt_plus.def.json
@@ -28,7 +28,7 @@
[ 3, 3 ]
]
},
- "gantry_height": { "default_value": 0 },
+ "gantry_height": { "value": "0" },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
@@ -41,23 +41,15 @@
"layer_height": { "default_value": 0.2 },
"wall_thickness": { "default_value": 0.8 },
"top_bottom_thickness": { "default_value": 0.3 },
- "material_print_temperature": { "default_value": 195 },
- "material_bed_temperature": { "default_value": 60 },
"retraction_enable": { "default_value": true },
"retraction_speed": { "default_value": 50 },
"retraction_amount": { "default_value": 0.8 },
"retraction_hop": { "default_value": 0.075 },
"speed_print": { "default_value": 60 },
- "speed_infill": { "default_value": 100 },
- "speed_topbottom": { "default_value": 15 },
- "speed_travel": { "default_value": 150 },
"speed_layer_0": {
- "minimum_value": "0.1",
- "default_value": 15.0
+ "minimum_value": "0.1"
},
- "infill_overlap": { "default_value": 10 },
"cool_fan_enabled": { "default_value": false },
- "cool_fan_speed": { "default_value": 0 },
"skirt_line_count": { "default_value": 3 },
"skirt_gap": { "default_value": 4 },
"skirt_brim_minimal_length": { "default_value": 200 }
diff --git a/resources/definitions/mendel90.def.json b/resources/definitions/mendel90.def.json
index 85d82ae176..39cb4de8d3 100644
--- a/resources/definitions/mendel90.def.json
+++ b/resources/definitions/mendel90.def.json
@@ -68,7 +68,7 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_head_with_fans_polygon":
{
diff --git a/resources/definitions/monoprice_select_mini_v1.def.json b/resources/definitions/monoprice_select_mini_v1.def.json
index a516d54b18..4fe67fc92e 100644
--- a/resources/definitions/monoprice_select_mini_v1.def.json
+++ b/resources/definitions/monoprice_select_mini_v1.def.json
@@ -1,5 +1,4 @@
{
- "id": "monoprice_select_mini_v1",
"version": 2,
"name": "Monoprice Select Mini V1",
"inherits": "malyan_m200",
diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json
index bed4fb1adb..2364e49383 100644
--- a/resources/definitions/monoprice_select_mini_v2.def.json
+++ b/resources/definitions/monoprice_select_mini_v2.def.json
@@ -1,5 +1,4 @@
{
- "id": "monoprice_select_mini_v2",
"version": 2,
"name": "Monoprice Select Mini V2 (E3D)",
"inherits": "malyan_m200",
diff --git a/resources/definitions/monoprice_ultimate.def.json b/resources/definitions/monoprice_ultimate.def.json
index 48290f0941..445347b54e 100644
--- a/resources/definitions/monoprice_ultimate.def.json
+++ b/resources/definitions/monoprice_ultimate.def.json
@@ -1,52 +1,48 @@
{
- "version": 2,
- "name": "Monoprice Ultimate",
- "inherits": "wanhao_d6",
- "metadata": {
- "visible": true,
- "author": "Danny Tuppeny",
- "manufacturer": "monoprice",
- "file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
- "has_materials": true,
- "platform": "wanhao_200_200_platform.obj",
- "platform_texture": "Wanhaobackplate.png",
- "machine_extruder_trains": {
- "0": "wanhao_d6_extruder_0"
+ "version": 2,
+ "name": "Monoprice Ultimate",
+ "inherits": "wanhao_d6",
+ "metadata": {
+ "visible": true,
+ "author": "Danny Tuppeny",
+ "manufacturer": "Monoprice",
+ "file_formats": "text/x-gcode",
+ "icon": "wanhao-icon.png",
+ "has_materials": true,
+ "platform": "wanhao_200_200_platform.obj",
+ "platform_texture": "Wanhaobackplate.png",
+ "machine_extruder_trains": {
+ "0": "wanhao_d6_extruder_0"
+ },
+ "platform_offset": [0, -28, 0]
},
- "platform_offset": [
- 0,
- -28,
- 0
- ]
- },
- "overrides": {
- "machine_name": {
- "default_value": "Monoprice Ultimate"
- },
- "machine_max_acceleration_x": {
- "default_value": 3000
- },
- "machine_max_acceleration_y": {
- "default_value": 3000
- },
- "machine_max_acceleration_z": {
- "default_value": 100
- },
- "machine_max_acceleration_e": {
- "default_value": 500
- },
- "machine_acceleration": {
- "default_value": 800
- },
- "machine_max_jerk_xy": {
- "default_value": 10.0
- },
- "machine_max_jerk_z": {
- "default_value": 0.4
- },
- "machine_max_jerk_e": {
- "default_value": 1.0
+ "overrides": {
+ "machine_name": {
+ "default_value": "Monoprice Ultimate"
+ },
+ "machine_max_acceleration_x": {
+ "default_value": 3000
+ },
+ "machine_max_acceleration_y": {
+ "default_value": 3000
+ },
+ "machine_max_acceleration_z": {
+ "default_value": 100
+ },
+ "machine_max_acceleration_e": {
+ "default_value": 500
+ },
+ "machine_acceleration": {
+ "default_value": 800
+ },
+ "machine_max_jerk_xy": {
+ "default_value": 10.0
+ },
+ "machine_max_jerk_z": {
+ "default_value": 0.4
+ },
+ "machine_max_jerk_e": {
+ "default_value": 1.0
+ }
}
- }
}
diff --git a/resources/definitions/nwa3d_a31.def.json b/resources/definitions/nwa3d_a31.def.json
new file mode 100644
index 0000000000..1cfd02fe7f
--- /dev/null
+++ b/resources/definitions/nwa3d_a31.def.json
@@ -0,0 +1,64 @@
+{
+ "name": "NWA3D A31",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "DragonJe",
+ "manufacturer": "NWA 3D LLC",
+ "file_formats": "text/x-gcode",
+ "platform_offset": [0, 0, 0],
+ "has_materials": true,
+ "has_variants": true,
+ "variants_name": "Nozzle Size",
+ "preferred_variant_name": "Standard 0.4mm",
+ "preferred_quality_type": "normal",
+ "has_machine_quality": true,
+ "preferred_material": "generic_pla",
+ "machine_extruder_trains":
+ {
+ "0": "nwa3d_a31_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": {
+ "default_value": "NWA3D A31"
+ },
+ "machine_width": {
+ "default_value": 300
+ },
+ "machine_height": {
+ "default_value": 400
+ },
+ "machine_depth": {
+ "default_value": 300
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-30, 34],
+ [-30, -32],
+ [30, -32],
+ [30, 34]
+ ]
+ },
+ "gantry_height": {
+ "value": "30"
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "G28 ; Home\nG1 Z15.0 F6000 ; Move Z axis up 15mm\n ; Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0"
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0\nM140 S0\n ; Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"
+ }
+ }
+}
diff --git a/resources/definitions/nwa3d_a5.def.json b/resources/definitions/nwa3d_a5.def.json
index 3deb0027fd..1631860d47 100644
--- a/resources/definitions/nwa3d_a5.def.json
+++ b/resources/definitions/nwa3d_a5.def.json
@@ -10,55 +10,53 @@
"platform_offset": [0, 0, 0],
"has_materials": true,
"has_variants": false,
- "has_machine_materials": true,
- "has_variant_materials": false,
"preferred_quality_type": "normal",
"has_machine_quality": true,
"preferred_material": "generic_pla",
- "machine_extruder_trains":
+ "machine_extruder_trains":
{
"0": "nwa3d_a5_extruder_0"
}
},
-
+
"overrides": {
- "machine_name": {
- "default_value": "NWA3D A5"
+ "machine_name": {
+ "default_value": "NWA3D A5"
},
- "machine_width": {
- "default_value": 125
+ "machine_width": {
+ "default_value": 125
},
- "machine_height": {
- "default_value": 100
+ "machine_height": {
+ "default_value": 100
},
- "machine_depth": {
- "default_value": 150
+ "machine_depth": {
+ "default_value": 150
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
- [-30, 34],
- [-30, -32],
- [30, -32],
+ [-30, 34],
+ [-30, -32],
+ [30, -32],
[30, 34]
- ]
+ ]
},
- "gantry_height": {
- "default_value": 30
+ "gantry_height": {
+ "value": "30"
},
- "machine_heated_bed": {
- "default_value": false
+ "machine_heated_bed": {
+ "default_value": false
},
"material_diameter": {
"default_value": 1.75
},
- "machine_gcode_flavor": {
- "default_value": "RepRap (RepRap)"
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (RepRap)"
},
- "machine_start_gcode": {
- "default_value": "G28 ; Home\nG1 Z15.0 F6000 ; Move Z axis up 15mm\n ; Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0"
+ "machine_start_gcode": {
+ "default_value": "G28 ; Home\nG1 Z15.0 F6000 ; Move Z axis up 15mm\n ; Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0"
},
- "machine_end_gcode": {
- "default_value": "M104 S0\nM140 S0\n ; Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"
+ "machine_end_gcode": {
+ "default_value": "M104 S0\nM140 S0\n ; Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"
}
}
}
diff --git a/resources/definitions/ord.def.json b/resources/definitions/ord.def.json
index de410b0d58..4a550602f2 100644
--- a/resources/definitions/ord.def.json
+++ b/resources/definitions/ord.def.json
@@ -19,12 +19,9 @@
},
"overrides": {
- "material_bed_temperature": { "default_value": 60 },
"prime_tower_size": { "default_value": 7.0710678118654755 },
"infill_sparse_density": { "default_value": 15 },
- "speed_travel": { "default_value": 150 },
"layer_height": { "default_value": 0.3 },
- "material_print_temperature": { "default_value": 240 },
"machine_extruder_count": { "default_value": 5 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json
index a578cc4240..8d7754a9ef 100644
--- a/resources/definitions/peopoly_moai.def.json
+++ b/resources/definitions/peopoly_moai.def.json
@@ -126,9 +126,6 @@
"adhesion_type": {
"value": "'none'"
},
- "acceleration_enabled": {
- "value": "False"
- },
"print_sequence": {
"enabled": false
},
@@ -173,8 +170,8 @@
"minimum_polygon_circumference": {
"value": "0.1"
},
- "meshfix_maximum_resolution": {
- "value": "0.005"
+ "meshfix_maximum_deviation": {
+ "value": "0.003"
},
"skin_outline_count": {
"value": 0
@@ -251,10 +248,6 @@
"expand_skins_expand_distance": {
"value": "( wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x ) / 2"
},
- "max_feedrate_z_override": {
- "value": 0,
- "enabled": false
- },
"flow_rate_max_extrusion_offset": {
"enabled": false
},
diff --git a/resources/definitions/printrbot_play.def.json b/resources/definitions/printrbot_play.def.json
index e3a18a4eee..bf52363800 100644
--- a/resources/definitions/printrbot_play.def.json
+++ b/resources/definitions/printrbot_play.def.json
@@ -27,9 +27,8 @@
"retraction_speed": { "default_value": 45},
"adhesion_type": { "default_value": "skirt" },
"machine_head_with_fans_polygon": { "default_value": [[-32,999],[37,999],[37,-32],[-32,-32]] },
- "gantry_height": { "default_value": 55 },
+ "gantry_height": { "value": "55" },
"speed_print": { "default_value": 50 },
- "speed_travel": { "default_value": 55 },
"machine_max_feedrate_x": {"default_value": 125},
"machine_max_feedrate_y": {"default_value": 125},
"machine_max_feedrate_z": { "default_value": 5 },
diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json
index fb65b77fa5..760ff383d1 100644
--- a/resources/definitions/printrbot_simple.def.json
+++ b/resources/definitions/printrbot_simple.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Calvindog717",
- "manufacturer": "PrintrBot",
+ "manufacturer": "Printrbot",
"platform": "printrbot_simple_metal_platform.stl",
"platform_offset": [0, -3.45, 0],
"file_formats": "text/x-gcode",
@@ -30,7 +30,6 @@
[55, -99999]
]
},
- "gantry_height": { "default_value": 99999 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
diff --git a/resources/definitions/printrbot_simple_extended.def.json b/resources/definitions/printrbot_simple_extended.def.json
index 1e004a8ca3..06c639f024 100644
--- a/resources/definitions/printrbot_simple_extended.def.json
+++ b/resources/definitions/printrbot_simple_extended.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "samsector",
- "manufacturer": "PrintrBot",
+ "manufacturer": "Printrbot",
"platform": "printrbot_simple_metal_upgrade.stl",
"platform_offset": [0, -0.3, 0],
"file_formats": "text/x-gcode",
@@ -30,7 +30,7 @@
[ -49, -20 ]
]
},
- "gantry_height": { "default_value": 99999 },
+ "gantry_height": { "value": "99999" },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
diff --git a/resources/definitions/printrbot_simple_makers_kit.def.json b/resources/definitions/printrbot_simple_makers_kit.def.json
index ad6ecee21e..1223f2a4d9 100644
--- a/resources/definitions/printrbot_simple_makers_kit.def.json
+++ b/resources/definitions/printrbot_simple_makers_kit.def.json
@@ -27,7 +27,7 @@
[60, -10]
]
},
- "gantry_height": { "default_value": 1000 },
+ "gantry_height": { "value": "1000" },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
diff --git a/resources/definitions/prusa_i3.def.json b/resources/definitions/prusa_i3.def.json
index 1f0eb37aec..267a7ba4e6 100644
--- a/resources/definitions/prusa_i3.def.json
+++ b/resources/definitions/prusa_i3.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Quillford",
- "manufacturer": "Prusajr",
+ "manufacturer": "Prusa3D",
"file_formats": "text/x-gcode",
"platform": "prusai3_platform.stl",
"machine_extruder_trains":
@@ -31,14 +31,6 @@
"machine_center_is_zero": {
"default_value": false
},
- "machine_head_polygon": {
- "default_value": [
- [-75, -18],
- [-75, 35],
- [18, 35],
- [18, -18]
- ]
- },
"machine_head_with_fans_polygon": {
"default_value": [
[-75, -18],
@@ -48,7 +40,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/prusa_i3_mk2.def.json b/resources/definitions/prusa_i3_mk2.def.json
index 5c5583b56f..5ae541049d 100644
--- a/resources/definitions/prusa_i3_mk2.def.json
+++ b/resources/definitions/prusa_i3_mk2.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Apsu, Nounours2099",
- "manufacturer": "Prusa Research",
+ "manufacturer": "Prusa3D",
"file_formats": "text/x-gcode",
"platform": "prusai3_platform.stl",
"has_materials": true,
@@ -22,16 +22,13 @@
"machine_height": { "default_value": 200 },
"machine_depth": { "default_value": 210 },
"machine_center_is_zero": { "default_value": false },
- "material_bed_temperature": { "default_value": 55 },
"layer_height": { "default_value": 0.1 },
"layer_height_0": { "default_value": 0.15 },
"retraction_amount": { "default_value": 0.8 },
"retraction_speed": { "default_value": 35 },
- "retraction_retract_speed": { "default_value": 35 },
- "retraction_prime_speed": { "default_value": 35 },
"adhesion_type": { "default_value": "skirt" },
"machine_head_with_fans_polygon": { "default_value": [[-31,31],[34,31],[34,-40],[-31,-40]] },
- "gantry_height": { "default_value": 28 },
+ "gantry_height": { "value": "28" },
"machine_max_feedrate_z": { "default_value": 12 },
"machine_max_feedrate_e": { "default_value": 120 },
"machine_max_acceleration_z": { "default_value": 500 },
diff --git a/resources/definitions/prusa_i3_mk3.def.json b/resources/definitions/prusa_i3_mk3.def.json
new file mode 100644
index 0000000000..eddc1d88df
--- /dev/null
+++ b/resources/definitions/prusa_i3_mk3.def.json
@@ -0,0 +1,50 @@
+{
+ "version": 2,
+ "name": "Prusa i3 Mk3/Mk3s",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Prusa Research",
+ "manufacturer": "Prusa3D",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker2",
+ "platform": "Original_Prusa_i3_MK3S_MK3_platform.stl",
+ "has_materials": true,
+ "machine_extruder_trains":
+ {
+ "0": "prusa_i3_mk3_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Prusa i3 Mk3/Mk3s" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 250 },
+ "machine_height": { "default_value": 210 },
+ "machine_depth": { "default_value": 210 },
+ "machine_center_is_zero": { "default_value": false },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "layer_height": { "default_value": 0.15 },
+ "layer_height_0": { "default_value": 0.2 },
+ "retraction_amount": { "default_value": 0.8 },
+ "retraction_speed": { "default_value": 35 },
+ "adhesion_type": { "default_value": "skirt" },
+ "machine_head_with_fans_polygon": { "default_value": [[-31,31],[34,31],[34,-40],[-31,-40]] },
+ "gantry_height": { "value": 28 },
+ "machine_max_feedrate_z": { "default_value": 12 },
+ "machine_max_feedrate_e": { "default_value": 120 },
+ "machine_max_acceleration_z": { "default_value": 500 },
+ "machine_acceleration": { "default_value": 1000 },
+ "machine_max_jerk_xy": { "default_value": 10 },
+ "machine_max_jerk_z": { "default_value": 0.2 },
+ "machine_max_jerk_e": { "default_value": 2.5 },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode": {
+ "default_value": "G21 ; set units to millimeters\nG90 ; use absolute positioning\nM82 ; absolute extrusion mode\nM104 S{material_print_temperature_layer_0} ; set extruder temp\nM140 S{material_bed_temperature_layer_0} ; set bed temp\nM190 S{material_bed_temperature_layer_0} ; wait for bed temp\nM109 S{material_print_temperature_layer_0} ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG92 E0.0 ; reset extruder distance position\nG1 Y-3.0 F1000.0 ; go outside print area\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E21.5 F1000.0 ; intro line\nG92 E0.0 ; reset extruder distance position"
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y210; home X axis and push Y forward\nM84 ; disable motors"
+ }
+ }
+}
diff --git a/resources/definitions/prusa_i3_xl.def.json b/resources/definitions/prusa_i3_xl.def.json
index 9931be5c72..dae1bdce4f 100644
--- a/resources/definitions/prusa_i3_xl.def.json
+++ b/resources/definitions/prusa_i3_xl.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "guigashm",
- "manufacturer": "Prusajr",
+ "manufacturer": "Prusa3D",
"file_formats": "text/x-gcode",
"platform": "prusai3_xl_platform.stl",
"machine_extruder_trains":
@@ -31,7 +31,7 @@
"machine_center_is_zero": {
"default_value": false
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
[-75, -18],
[-75, 35],
@@ -40,7 +40,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/punchtec_connect_xl.def.json b/resources/definitions/punchtec_connect_xl.def.json
index 1efdd226fd..9bae80b0ac 100644
--- a/resources/definitions/punchtec_connect_xl.def.json
+++ b/resources/definitions/punchtec_connect_xl.def.json
@@ -16,16 +16,10 @@
},
"overrides": {
- "machine_head_polygon": { "default_value": [[ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0]] },
- "speed_travel": { "default_value": 150 },
+ "machine_head_with_fans_polygon": { "default_value": [[ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0]] },
"prime_tower_size": { "default_value": 8.660254037844387 },
- "speed_wall_x": { "default_value": 40 },
- "speed_wall_0": { "default_value": 40 },
- "speed_topbottom": { "default_value": 40 },
"layer_height": { "default_value": 0.2 },
- "material_print_temperature": { "default_value": 195 },
"speed_print": { "default_value": 40 },
- "speed_infill": { "default_value": 40 },
"machine_extruder_count": { "default_value": 2 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/raise3D_N2_dual.def.json b/resources/definitions/raise3D_N2_dual.def.json
index eff5884da8..530ad79d19 100644
--- a/resources/definitions/raise3D_N2_dual.def.json
+++ b/resources/definitions/raise3D_N2_dual.def.json
@@ -58,7 +58,7 @@
"default_value": "skirt"
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -67,7 +67,7 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\nT1; left tool\n; set extruder steps per mm\nM92 E140\nT0; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\nT1; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing…\nM1001\n"
+ "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\nT1; left tool\n; set extruder steps per mm\nM92 E140\nT0; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\nT1; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing...\nM1001\n"
},
"machine_end_gcode": {
"default_value": "M107\nM1002\nM104 S0 T1\nM104 S0 T0\nM140 S0\nM117 Print Complete.\nG28 X0 Y0\nG91\nG1 Z10\nG90\nM84"
@@ -76,10 +76,10 @@
"default_value": 2
},
"prime_tower_position_x": {
- "default_value": 195
+ "value": "195"
},
"prime_tower_position_y": {
- "default_value": 149
+ "value": "149"
}
}
}
diff --git a/resources/definitions/raise3D_N2_plus_dual.def.json b/resources/definitions/raise3D_N2_plus_dual.def.json
index 06de52321a..ffc4afec16 100644
--- a/resources/definitions/raise3D_N2_plus_dual.def.json
+++ b/resources/definitions/raise3D_N2_plus_dual.def.json
@@ -58,7 +58,7 @@
"default_value": "skirt"
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -67,7 +67,7 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\nT1; left tool\n; set extruder steps per mm\nM92 E140\nT0; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\nT1; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing…\nM1001\n"
+ "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\nT1; left tool\n; set extruder steps per mm\nM92 E140\nT0; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\nT1; left tool\nG92 E0 E1\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing...\nM1001\n"
},
"machine_end_gcode": {
"default_value": "M107\nM1002\nM104 S0 T1\nM104 S0 T0\nM140 S0\nM117 Print Complete.\nG28 X0 Y0\nG91\nG1 Z10\nG90\nM84"
@@ -76,10 +76,10 @@
"default_value": 2
},
"prime_tower_position_x": {
- "default_value": 195
+ "value": "195"
},
"prime_tower_position_y": {
- "default_value": 149
+ "value": "149"
}
}
}
diff --git a/resources/definitions/raise3D_N2_plus_single.def.json b/resources/definitions/raise3D_N2_plus_single.def.json
index b829147160..ccb169efb1 100644
--- a/resources/definitions/raise3D_N2_plus_single.def.json
+++ b/resources/definitions/raise3D_N2_plus_single.def.json
@@ -57,7 +57,7 @@
"default_value": "skirt"
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -66,16 +66,16 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing…\nM1001\n"
+ "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing...\nM1001\n"
},
"machine_end_gcode": {
"default_value": "M107\nM1002\nM104 S0 T1\nM104 S0 T0\nM140 S0\nM117 Print Complete.\nG28 X0 Y0\nG91\nG1 Z10\nG90\nM84"
},
"prime_tower_position_x": {
- "default_value": 195
+ "value": "195"
},
"prime_tower_position_y": {
- "default_value": 149
+ "value": "149"
}
}
}
diff --git a/resources/definitions/raise3D_N2_single.def.json b/resources/definitions/raise3D_N2_single.def.json
index 899da5188f..f0915d1a31 100644
--- a/resources/definitions/raise3D_N2_single.def.json
+++ b/resources/definitions/raise3D_N2_single.def.json
@@ -57,7 +57,7 @@
"default_value": "skirt"
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -66,16 +66,16 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing…\nM1001\n"
+ "default_value": "G90\nG21\n; home all axes\nG28\nG92 X0 Y0 Z0\n; move heatbed into position\nG1 X20.0 Y20.0 Z1.0 F1000\n; zero extruders\nG92 E0 E1\nT0; right tool\n; set extruder steps per mm\nM92 E140\n; purge nozzle\nG1 E25 F250\n; zero extruders\nG92 E0 E1\n; move heatbed down a little more\nG1 Z5.0 F20\n; wait 600ms\nG4 600\n; move to tack down the strands\nG1 X20.0 Y30.0 Z0 F9000\n; wait 600ms\nG4 600\n;move up a bit\nG1 Z5.0 F9000\n; wait 300ms\nG4 300\n;fast move to center\nG1 X152.5 Y152.5 F9000\nT0\n;Raise3D Job Start\nM117 Printing...\nM1001\n"
},
"machine_end_gcode": {
"default_value": "M107\nM1002\nM104 S0 T1\nM104 S0 T0\nM140 S0\nM117 Print Complete.\nG28 X0 Y0\nG91\nG1 Z10\nG90\nM84"
},
"prime_tower_position_x": {
- "default_value": 195
+ "value": "195"
},
"prime_tower_position_y": {
- "default_value": 149
+ "value": "149"
}
}
}
diff --git a/resources/definitions/renkforce_rf100.def.json b/resources/definitions/renkforce_rf100.def.json
index 41549fb531..2ff34a7519 100644
--- a/resources/definitions/renkforce_rf100.def.json
+++ b/resources/definitions/renkforce_rf100.def.json
@@ -183,7 +183,7 @@
"value": "False"
},
"support_infill_rate": {
- "value": "15.0"
+ "value": "15 if support_enable else 0 if support_tree_enable else 15"
},
"support_pattern": {
"default_value": "lines"
diff --git a/resources/definitions/rigid3d.def.json b/resources/definitions/rigid3d.def.json
index 43ffd6924a..ba90894f7d 100644
--- a/resources/definitions/rigid3d.def.json
+++ b/resources/definitions/rigid3d.def.json
@@ -21,27 +21,17 @@
"machine_end_gcode": {
"default_value": " ; -- END GCODE --\n G1 X0 Y230 ; Get extruder out of way.\n M107 ; Turn off fan\n G91 ; Relative positioning\n G0 Z20 ; Lift extruder up\n T0\n G1 E-1 ; Reduce filament pressure\n M104 T0 S0 ; Turn ectruder heater off\n G90 ; Absolute positioning\n G92 E0 ; Reset extruder position\n M140 S0 ; Disable heated bed\n M84 ; Turn steppers off\n ; -- end of END GCODE --\n"
},
- "machine_head_polygon": { "default_value": [[ 22, 67], [ 22, 51], [ 36, 51], [ 36, 67]] },
+ "machine_head_with_fans_polygon": { "default_value": [[ 22, 67], [ 22, 51], [ 36, 51], [ 36, 67]] },
"skirt_gap": { "default_value": 5.0 },
"cool_min_layer_time": { "default_value": 10 },
"prime_tower_size": { "default_value": 7.745966692414834 },
- "speed_wall_x": { "default_value": 40 },
- "speed_travel": { "default_value": 100 },
- "bottom_thickness": { "default_value": 0.75 },
"layer_height_0": { "default_value": 0.25 },
"support_angle": { "default_value": 45 },
- "material_bed_temperature": { "default_value": 100 },
- "top_thickness": { "default_value": 0.75 },
- "material_print_temperature": { "default_value": 235 },
"retraction_speed": { "default_value": 60.0 },
"wall_thickness": { "default_value": 0.8 },
- "retraction_min_travel": { "default_value": 2 },
- "speed_wall_0": { "default_value": 30 },
"retraction_amount": { "default_value": 1 },
- "speed_topbottom": { "default_value": 30 },
"layer_height": { "default_value": 0.25 },
"speed_print": { "default_value": 40 },
- "speed_infill": { "default_value": 40 },
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/rigid3d_3rdgen.def.json b/resources/definitions/rigid3d_3rdgen.def.json
index bb3414b75d..6e1a93fb40 100644
--- a/resources/definitions/rigid3d_3rdgen.def.json
+++ b/resources/definitions/rigid3d_3rdgen.def.json
@@ -21,24 +21,16 @@
"machine_end_gcode": {
"default_value": " ; -- END GCODE --\n G1 X0 Y230 ; Get extruder out of way.\n M107 ; Turn off fan\n G91 ; Relative positioning\n G0 Z20 ; Lift extruder up\n T0\n G1 E-1 ; Reduce filament pressure\n M104 T0 S0 ; Turn extruder heater off\n G90 ; Absolute positioning\n G92 E0 ; Reset extruder position\n M140 S0 ; Disable heated bed\n M84 ; Turn steppers off\n ; -- end of END GCODE --\n"
},
- "machine_head_polygon": { "default_value": [[ 18, 0], [ 18, 65], [ 32, 65], [ 32, 0]] },
+ "machine_head_with_fans_polygon": { "default_value": [[ 18, 0], [ 18, 65], [ 32, 65], [ 32, 0]] },
"cool_min_layer_time": { "default_value": 10 },
"prime_tower_size": { "default_value": 7.745966692414834 },
"skirt_gap": { "default_value": 5.0 },
- "speed_travel": { "default_value": 120 },
- "bottom_thickness": { "default_value": 0.75 },
"layer_height_0": { "default_value": 0.25 },
"support_angle": { "default_value": 45 },
- "material_bed_temperature": { "default_value": 100 },
- "retraction_min_travel": { "default_value": 2 },
- "speed_wall_0": { "default_value": 30 },
"retraction_speed": { "default_value": 60.0 },
"wall_thickness": { "default_value": 0.8 },
- "material_print_temperature": { "default_value": 235 },
"retraction_amount": { "default_value": 1 },
- "speed_topbottom": { "default_value": 25 },
"layer_height": { "default_value": 0.25 },
- "top_thickness": { "default_value": 0.75 },
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/rigid3d_hobby.def.json b/resources/definitions/rigid3d_hobby.def.json
index db48195fe0..d89c1aeaff 100644
--- a/resources/definitions/rigid3d_hobby.def.json
+++ b/resources/definitions/rigid3d_hobby.def.json
@@ -15,27 +15,19 @@
},
"overrides": {
- "machine_head_polygon": { "default_value": [[ 16, 30], [ 16, 45], [ 16, 45], [ 16, 30]] },
+ "machine_head_with_fans_polygon": { "default_value": [[ 16, 30], [ 16, 45], [ 16, 45], [ 16, 30]] },
"prime_tower_size": { "default_value": 8.660254037844387 },
- "speed_travel": { "default_value": 40 },
"skirt_gap": { "default_value": 5.0 },
"cool_min_layer_time": { "default_value": 15 },
"support_pattern": { "default_value": "grid" },
"layer_height_0": { "default_value": 0.25 },
- "speed_wall_x": { "default_value": 30 },
"skirt_line_count": { "default_value": 2 },
"support_angle": { "default_value": 45 },
- "speed_topbottom": { "default_value": 20 },
- "material_print_temperature": { "default_value": 205 },
"retraction_speed": { "default_value": 80 },
"wall_thickness": { "default_value": 0.8 },
- "retraction_min_travel": { "default_value": 2 },
- "speed_wall_0": { "default_value": 20 },
"retraction_amount": { "default_value": 2 },
- "speed_layer_0": { "default_value": 15 },
"layer_height": { "default_value": 0.2 },
"speed_print": { "default_value": 30 },
- "speed_infill": { "default_value": 30 },
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": false },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/rigid3d_mucit.def.json b/resources/definitions/rigid3d_mucit.def.json
index 42cd99a3bd..75853fab8b 100644
--- a/resources/definitions/rigid3d_mucit.def.json
+++ b/resources/definitions/rigid3d_mucit.def.json
@@ -76,14 +76,9 @@
"default_value": true
},
"cool_fan_speed": {
- "default_value": 100,
"value": "100"
},
- "cool_fan_speed_min": {
- "default_value": 0
- },
"cool_fan_full_at_height": {
- "default_value": 0.5,
"value": "0.5"
},
"support_z_distance": {
diff --git a/resources/definitions/rigid3d_zero.def.json b/resources/definitions/rigid3d_zero.def.json
index f55f913a56..54bd2c3dca 100644
--- a/resources/definitions/rigid3d_zero.def.json
+++ b/resources/definitions/rigid3d_zero.def.json
@@ -21,24 +21,14 @@
"machine_end_gcode": {
"default_value": " ; -- END GCODE --\n G1 X0 Y230 ; Get extruder out of way.\n M107 ; Turn off fan\n G91 ; Relative positioning\n G0 Z20 ; Lift extruder up\n T0\n G1 E-1 ; Reduce filament pressure\n M104 T0 S0 ; Turn ectruder heater off\n G90 ; Absolute positioning\n G92 E0 ; Reset extruder position\n M140 S0 ; Disable heated bed\n M84 ; Turn steppers off\n ; -- end of END GCODE --\n"
},
- "machine_head_polygon": { "default_value": [[ 40, 15], [ 40, 60], [ 30, 60], [ 30, 15]] },
+ "machine_head_with_fans_polygon": { "default_value": [[ 40, 15], [ 40, 60], [ 30, 60], [ 30, 15]] },
"support_pattern": { "default_value": "grid" },
"cool_min_layer_time": { "default_value": 10 },
- "speed_travel": { "default_value": 80 },
"support_angle": { "default_value": 45 },
- "retraction_min_travel": { "default_value": 2 },
- "speed_wall_0": { "default_value": 20 },
- "speed_layer_0": { "default_value": 15 },
- "speed_infill": { "default_value": 30 },
- "speed_topbottom": { "default_value": 30 },
"prime_tower_size": { "default_value": 7.745966692414834 },
"skirt_line_count": { "default_value": 2 },
- "speed_wall_x": { "default_value": 30 },
- "bottom_thickness": { "default_value": 0.75 },
"layer_height_0": { "default_value": 0.25 },
- "top_thickness": { "default_value": 0.75 },
"wall_thickness": { "default_value": 0.8 },
- "material_print_temperature": { "default_value": 195 },
"retraction_amount": { "default_value": 1.5 },
"skirt_gap": { "default_value": 5.0 },
"layer_height": { "default_value": 0.25 },
diff --git a/resources/definitions/rigid3d_zero2.def.json b/resources/definitions/rigid3d_zero2.def.json
index 09390ed8b5..cc922769f7 100644
--- a/resources/definitions/rigid3d_zero2.def.json
+++ b/resources/definitions/rigid3d_zero2.def.json
@@ -44,9 +44,6 @@
"material_print_temperature": {
"value": 235
},
- "material_bed_temperature": {
- "default_value": 100
- },
"speed_print": {
"default_value": 40
},
@@ -55,7 +52,7 @@
},
"speed_travel": {
"value": 100
- },
+ },
"support_enable": {
"default_value": false
},
@@ -81,7 +78,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 25
+ "value": "25"
},
"machine_gcode_flavor": {
"default_value": "RepRap"
@@ -90,14 +87,9 @@
"default_value": false
},
"cool_fan_speed": {
- "default_value": 50,
"value": 50
},
- "cool_fan_speed_min": {
- "default_value": 0
- },
"cool_fan_full_at_height": {
- "default_value": 1.0,
"value": 1.0
},
"support_z_distance": {
diff --git a/resources/definitions/rigidbot.def.json b/resources/definitions/rigidbot.def.json
index 5eb346c7ca..d6fb4f1651 100644
--- a/resources/definitions/rigidbot.def.json
+++ b/resources/definitions/rigidbot.def.json
@@ -29,7 +29,7 @@
"default_value": true
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -49,37 +49,15 @@
"top_bottom_thickness": {
"default_value": 0.3
},
- "material_print_temperature": {
- "default_value": 195
- },
- "material_bed_temperature": {
- "default_value": 60
- },
"speed_print": {
"default_value": 60
},
- "speed_infill": {
- "default_value": 100
- },
- "speed_topbottom": {
- "default_value": 15
- },
- "speed_travel": {
- "default_value": 150
- },
"speed_layer_0": {
- "default_value": 15,
"minimum_value": "0.1"
},
- "infill_overlap": {
- "default_value": 10
- },
"cool_fan_enabled": {
"default_value": false
},
- "cool_fan_speed": {
- "default_value": 0
- },
"skirt_line_count": {
"default_value": 3
},
diff --git a/resources/definitions/rigidbot_big.def.json b/resources/definitions/rigidbot_big.def.json
index 581b6144a0..9568417acc 100644
--- a/resources/definitions/rigidbot_big.def.json
+++ b/resources/definitions/rigidbot_big.def.json
@@ -29,7 +29,7 @@
"default_value": true
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -49,37 +49,15 @@
"top_bottom_thickness": {
"default_value": 0.3
},
- "material_print_temperature": {
- "default_value": 195
- },
- "material_bed_temperature": {
- "default_value": 60
- },
"speed_print": {
"default_value": 60
},
- "speed_infill": {
- "default_value": 100
- },
- "speed_topbottom": {
- "default_value": 15
- },
- "speed_travel": {
- "default_value": 150
- },
"speed_layer_0": {
- "default_value": 15,
"minimum_value": "0.1"
},
- "infill_overlap": {
- "default_value": 10
- },
"cool_fan_enabled": {
"default_value": false
},
- "cool_fan_speed": {
- "default_value": 0
- },
"skirt_line_count": {
"default_value": 3
},
diff --git a/resources/definitions/robo_3d_r1.def.json b/resources/definitions/robo_3d_r1.def.json
index 8d7698e198..36b8addd27 100644
--- a/resources/definitions/robo_3d_r1.def.json
+++ b/resources/definitions/robo_3d_r1.def.json
@@ -22,28 +22,16 @@
"default_value": " M104 S0 ;extruder heater off\n M140 S0 ;heated bed heater off (if you have it)\n G91 ;relative positioning\n G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n G1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\n G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\n M84 ;steppers off\n G90 ;absolute positioning\n"
},
"cool_min_layer_time": { "default_value": 7 },
- "speed_topbottom": { "default_value": 40 },
"retraction_speed": { "default_value": 50 },
- "layer_0_z_overlap": { "default_value": 0.2 },
"cool_min_speed": { "default_value": 19 },
- "material_bed_temperature": { "default_value": 60 },
"support_angle": { "default_value": 50 },
- "speed_layer_0": { "default_value": 30 },
- "line_width": { "default_value": 0.4 },
- "speed_infill": { "default_value": 60 },
"prime_tower_size": { "default_value": 8.660254037844387 },
"support_enable": { "default_value": true },
- "cool_fan_full_at_height": { "default_value": 0.1 },
- "bottom_thickness": { "default_value": 1.2 },
"raft_airgap": { "default_value": 0.2 },
"layer_height_0": { "default_value": 0.15 },
- "top_thickness": { "default_value": 1.2 },
- "speed_wall_0": { "default_value": 40 },
- "retraction_min_travel": { "default_value": 5 },
"material_flow": { "default_value": 100 },
"infill_sparse_density": { "default_value": 10 },
"wall_thickness": { "default_value": 1.2 },
- "material_print_temperature": { "default_value": 190 },
"retraction_amount": { "default_value": 3 },
"layer_height": { "default_value": 0.2 },
"speed_print": { "default_value": 40 },
diff --git a/resources/definitions/seemecnc_artemis.def.json b/resources/definitions/seemecnc_artemis.def.json
index ec92f528d7..88c1d84b3d 100644
--- a/resources/definitions/seemecnc_artemis.def.json
+++ b/resources/definitions/seemecnc_artemis.def.json
@@ -27,13 +27,11 @@
"machine_name": { "default_value": "Artemis" },
"machine_shape": { "default_value": "elliptic" },
"machine_width": { "default_value": 290 },
- "relative_extrusion": { "default_value": false },
+ "relative_extrusion": { "value": "False" },
"retraction_amount": { "default_value": 3.2 },
"retraction_combing": { "default_value": "off" },
"retraction_hop_enabled": { "default_value": true },
"retraction_hop_only_when_collides": { "default_value": false },
- "retraction_prime_speed": { "default_value": 45 },
- "retraction_retract_speed": { "default_value": 45 },
"retraction_speed": { "default_value": 45 },
"machine_start_gcode": {
"default_value": "G28\nG1 Z15.0 F10000\nG92 E0"
diff --git a/resources/definitions/seemecnc_v32.def.json b/resources/definitions/seemecnc_v32.def.json
index d4316c25d9..0f49410116 100644
--- a/resources/definitions/seemecnc_v32.def.json
+++ b/resources/definitions/seemecnc_v32.def.json
@@ -27,13 +27,11 @@
"machine_name": { "default_value": "Rostock Max V3.2" },
"machine_shape": { "default_value": "elliptic" },
"machine_width": { "default_value": 265 },
- "relative_extrusion": { "default_value": false },
+ "relative_extrusion": { "value": "False" },
"retraction_amount": { "default_value": 3.2 },
"retraction_combing": { "default_value": "off" },
"retraction_hop_enabled": { "default_value": true },
"retraction_hop_only_when_collides": { "default_value": false },
- "retraction_prime_speed": { "default_value": 45 },
- "retraction_retract_speed": { "default_value": 45 },
"retraction_speed": { "default_value": 45 },
"machine_start_gcode": {
"default_value": "G28\nG1 Z15.0 F10000\nG92 E0"
diff --git a/resources/definitions/skriware_2.def.json b/resources/definitions/skriware_2.def.json
new file mode 100644
index 0000000000..584cdd1708
--- /dev/null
+++ b/resources/definitions/skriware_2.def.json
@@ -0,0 +1,598 @@
+{
+ "name": "Skriware 2",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Skriware",
+ "manufacturer": "Skriware",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "platform_offset": [
+ 0,
+ 0,
+ 0
+ ],
+ "supports_usb_connection": false,
+ "platform": "skriware_2_platform.stl",
+ "machine_extruder_trains": {
+ "0": "skriware_2_extruder_0",
+ "1": "skriware_2_extruder_1"
+ }
+ },
+ "overrides": {
+ "jerk_print_layer_0": {
+ "value": "5"
+ },
+ "jerk_prime_tower": {
+ "value": "5"
+ },
+ "expand_skins_expand_distance": {
+ "value": "1.2"
+ },
+ "jerk_support_interface": {
+ "value": "5"
+ },
+ "jerk_travel_layer_0": {
+ "value": "5.0"
+ },
+ "wipe_retraction_prime_speed": {
+ "value": "30"
+ },
+ "material_standby_temperature": {
+ "default_value": 195
+ },
+ "acceleration_support_bottom": {
+ "value": "250"
+ },
+ "raft_base_line_width": {
+ "value": "0.5"
+ },
+ "raft_speed": {
+ "value": "30.0"
+ },
+ "jerk_topbottom": {
+ "value": "5"
+ },
+ "ironing_inset": {
+ "value": "0.2"
+ },
+ "acceleration_wall": {
+ "value": "250"
+ },
+ "cross_infill_pocket_size": {
+ "value": "5.333333333333333"
+ },
+ "jerk_support_roof": {
+ "value": "5"
+ },
+ "acceleration_print": {
+ "default_value": 250
+ },
+ "meshfix_maximum_travel_resolution": {
+ "value": "0.8"
+ },
+ "support_top_distance": {
+ "value": "0.22"
+ },
+ "acceleration_enabled": {
+ "default_value": true
+ },
+ "optimize_wall_printing_order": {
+ "default_value": true
+ },
+ "jerk_layer_0": {
+ "value": "5"
+ },
+ "infill_line_distance": {
+ "value": "5.333333333333333"
+ },
+ "acceleration_ironing": {
+ "value": "250"
+ },
+ "material_print_temperature_layer_0": {
+ "value": "195"
+ },
+ "bridge_skin_speed_2": {
+ "value": "15"
+ },
+ "acceleration_travel": {
+ "value": "250"
+ },
+ "switch_extruder_retraction_speed": {
+ "value": "30"
+ },
+ "jerk_print": {
+ "default_value": 5
+ },
+ "material_guid": {
+ "default_value": "0ff92885-617b-4144-a03c-9989872454bc"
+ },
+ "raft_interface_acceleration": {
+ "value": "250"
+ },
+ "acceleration_support_interface": {
+ "value": "250"
+ },
+ "cool_fan_full_layer": {
+ "value": "1"
+ },
+ "skirt_brim_minimal_length": {
+ "default_value": 50
+ },
+ "material_bed_temperature": {
+ "value": "50"
+ },
+ "speed_slowdown_layers": {
+ "default_value": 1
+ },
+ "speed_travel": {
+ "value": "150"
+ },
+ "skin_overlap": {
+ "value": "15"
+ },
+ "acceleration_infill": {
+ "value": "250"
+ },
+ "support_roof_material_flow": {
+ "value": "99"
+ },
+ "raft_base_jerk": {
+ "value": "5"
+ },
+ "retraction_retract_speed": {
+ "value": "30"
+ },
+ "infill_wipe_dist": {
+ "value": "0.1"
+ },
+ "jerk_wall_x": {
+ "value": "5"
+ },
+ "layer_height": {
+ "default_value": 0.2
+ },
+ "bottom_skin_expand_distance": {
+ "value": "1.2000000000000002"
+ },
+ "machine_start_gcode": {
+ "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG28 X0 Y0;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nM420 S1 Z0.9 ;enable bed levelling\nG1 Z10 F250 ;move the platform down 10mm\nM107 ;fan off\nM42 P11 S255 ;turn on front fan\nM140 S{material_bed_temperature}\nM104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nG1 F2500 Y260\nM190 S{material_bed_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nM60 ;enable E-FADE Algorithm\nM62 A ;filament sensor off\nG92 E0 ;zero the extruded length\nT1\nG92 E0;zero the extruded length\nG1 F300 Z0.3\nG1 F1200 X20\nG1 F1200 X180 E21 ;extrude 21 mm of feed stock\nG1 F1200 E15 ;retracting 6 mm\nG1 F2000 E21\nG1 F2000 E15\nG1 F300 Z1.5\nG92 E0 ;zero the extruded length again\nT0\nG92 E0 ;zero the extruded length\nG1 F1200 Y258\nG1 F300 Z0.3\nG1 F1200 X40 E21 ;extrude 21 mm of feed stock\nG1 F1200 E15 ;retracting 6 mm\nG1 F2000 E21\nG1 F2000 E15\nG1 Z1.5\nM61 A\nM63 A ;filament sensor on\nG92 E0 ;zero the extruded length again\nM58 ;end of Start G-Code and signal retract management"
+ },
+ "travel_retract_before_outer_wall": {
+ "default_value": true
+ },
+ "xy_offset_layer_0": {
+ "value": "-0.16"
+ },
+ "adhesion_type": {
+ "default_value": "raft"
+ },
+ "min_skin_width_for_expansion": {
+ "value": "0.671279704941824"
+ },
+ "support_bottom_material_flow": {
+ "value": "99"
+ },
+ "prime_tower_position_x": {
+ "value": "1"
+ },
+ "machine_depth": {
+ "default_value": 260
+ },
+ "retraction_speed": {
+ "default_value": 30
+ },
+ "support_skip_some_zags": {
+ "default_value": true
+ },
+ "remove_empty_first_layers": {
+ "default_value": false
+ },
+ "z_seam_x": {
+ "value": "115"
+ },
+ "support_xy_distance_overhang": {
+ "value": "0.5"
+ },
+ "support_tree_wall_thickness": {
+ "value": "0.4"
+ },
+ "acceleration_print_layer_0": {
+ "value": "250"
+ },
+ "support_xy_distance": {
+ "default_value": 0.8
+ },
+ "support_roof_line_distance": {
+ "value": "0.5714285714285714"
+ },
+ "jerk_enabled": {
+ "default_value": true
+ },
+ "min_infill_area": {
+ "default_value": 1
+ },
+ "travel_avoid_supports": {
+ "default_value": true
+ },
+ "bottom_layers": {
+ "value": "3"
+ },
+ "multiple_mesh_overlap": {
+ "default_value": 0
+ },
+ "retraction_hop_enabled": {
+ "default_value": true
+ },
+ "acceleration_topbottom": {
+ "value": "250"
+ },
+ "jerk_wall": {
+ "value": "5"
+ },
+ "jerk_wall_0": {
+ "value": "5"
+ },
+ "skin_overlap_mm": {
+ "value": "0.06"
+ },
+ "retraction_min_travel": {
+ "value": "1"
+ },
+ "support_interface_material_flow": {
+ "value": "99"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "speed_roofing": {
+ "value": "30.0"
+ },
+ "skin_outline_count": {
+ "default_value": 0
+ },
+ "skin_no_small_gaps_heuristic": {
+ "default_value": true
+ },
+ "top_bottom_pattern_0": {
+ "value": "'zigzag'"
+ },
+ "top_skin_expand_distance": {
+ "value": "1.2000000000000002"
+ },
+ "acceleration_travel_layer_0": {
+ "value": "250.0"
+ },
+ "prime_tower_min_volume": {
+ "default_value": 4
+ },
+ "switch_extruder_retraction_speeds": {
+ "default_value": 30
+ },
+ "skin_preshrink": {
+ "value": "1.2000000000000002"
+ },
+ "material_bed_temperature_layer_0": {
+ "value": "50"
+ },
+ "support_tree_collision_resolution": {
+ "value": "0.2"
+ },
+ "machine_height": {
+ "default_value": 210
+ },
+ "raft_acceleration": {
+ "value": "250"
+ },
+ "fill_outline_gaps": {
+ "default_value": true
+ },
+ "wall_x_material_flow": {
+ "value": "99"
+ },
+ "jerk_support_bottom": {
+ "value": "5"
+ },
+ "machine_end_gcode": {
+ "default_value": "M59\nG92 E1\nG1 E-1 F300\nM104 T0 S0\nM104 T1 S0\nM140 S0\nG28 X0 Y0\nM84\nM106 S0\nM107"
+ },
+ "infill_sparse_density": {
+ "default_value": 15
+ },
+ "meshfix_maximum_deviation": {
+ "default_value": 0.005
+ },
+ "wall_0_material_flow": {
+ "value": "99"
+ },
+ "material_adhesion_tendency": {
+ "default_value": 0
+ },
+ "prime_tower_flow": {
+ "value": "99"
+ },
+ "prime_tower_position_y": {
+ "value": "1"
+ },
+ "support_material_flow": {
+ "value": "99"
+ },
+ "retract_at_layer_change": {
+ "default_value": true
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ },
+ "wall_thickness": {
+ "default_value": 1.2
+ },
+ "support_infill_sparse_thickness": {
+ "value": "0.2"
+ },
+ "raft_surface_acceleration": {
+ "value": "250"
+ },
+ "roofing_layer_count": {
+ "value": "1"
+ },
+ "skirt_brim_line_width": {
+ "value": "0.5"
+ },
+ "jerk_support": {
+ "value": "5"
+ },
+ "raft_surface_jerk": {
+ "value": "5"
+ },
+ "speed_equalize_flow_max": {
+ "default_value": 40
+ },
+ "raft_surface_speed": {
+ "value": "30.0"
+ },
+ "jerk_travel": {
+ "value": "5"
+ },
+ "support_zag_skip_count": {
+ "value": "8"
+ },
+ "retraction_combing": {
+ "default_value": "infill"
+ },
+ "raft_interface_line_spacing": {
+ "value": "0.4"
+ },
+ "layer_height_0": {
+ "default_value": 0.2
+ },
+ "extruders_enabled_count": {
+ "value": "2"
+ },
+ "support_line_distance": {
+ "value": "1.3333333333333333"
+ },
+ "support_roof_density": {
+ "value": "70"
+ },
+ "raft_base_line_spacing": {
+ "value": "0.8"
+ },
+ "acceleration_prime_tower": {
+ "value": "250"
+ },
+ "skin_material_flow": {
+ "value": "99"
+ },
+ "support_z_distance": {
+ "default_value": 0.22
+ },
+ "bottom_skin_preshrink": {
+ "value": "1.2000000000000002"
+ },
+ "jerk_skirt_brim": {
+ "value": "5"
+ },
+ "z_seam_y": {
+ "value": "180"
+ },
+ "skirt_line_count": {
+ "default_value": 2
+ },
+ "raft_margin": {
+ "default_value": 4
+ },
+ "infill_material_flow": {
+ "value": "99"
+ },
+ "wipe_retraction_retract_speed": {
+ "value": "30"
+ },
+ "z_seam_corner": {
+ "default_value": "z_seam_corner_weighted"
+ },
+ "support_roof_height": {
+ "value": "0.4"
+ },
+ "top_layers": {
+ "value": "4"
+ },
+ "support_infill_rate": {
+ "value": "30"
+ },
+ "raft_interface_speed": {
+ "value": "35"
+ },
+ "default_material_print_temperature": {
+ "default_value": 195
+ },
+ "acceleration_layer_0": {
+ "value": "250"
+ },
+ "support_skip_zag_per_mm": {
+ "default_value": 10
+ },
+ "material_initial_print_temperature": {
+ "value": "195"
+ },
+ "raft_interface_jerk": {
+ "value": "5"
+ },
+ "machine_width": {
+ "default_value": 210
+ },
+ "wall_line_count": {
+ "value": "3"
+ },
+ "retraction_amount": {
+ "default_value": 3
+ },
+ "infill_sparse_thickness": {
+ "value": "0.2"
+ },
+ "support_initial_layer_line_distance": {
+ "value": "1.3333333333333333"
+ },
+ "jerk_support_infill": {
+ "value": "5"
+ },
+ "acceleration_roofing": {
+ "value": "250"
+ },
+ "retraction_extrusion_window": {
+ "value": "3"
+ },
+ "raft_interface_line_width": {
+ "value": "0.4"
+ },
+ "acceleration_support_roof": {
+ "value": "250"
+ },
+ "support_brim_line_count": {
+ "value": "16"
+ },
+ "layer_0_z_overlap": {
+ "value": "0.1"
+ },
+ "support_angle": {
+ "default_value": 60
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "raft_surface_thickness": {
+ "value": "0.2"
+ },
+ "cool_min_layer_time": {
+ "default_value": 10
+ },
+ "gantry_height": {
+ "value": "210"
+ },
+ "raft_airgap": {
+ "default_value": 0.2
+ },
+ "acceleration_skirt_brim": {
+ "value": "250"
+ },
+ "skirt_brim_material_flow": {
+ "value": "99"
+ },
+ "jerk_infill": {
+ "value": "5"
+ },
+ "roofing_material_flow": {
+ "value": "99"
+ },
+ "support_use_towers": {
+ "default_value": false
+ },
+ "ooze_shield_angle": {
+ "default_value": 50
+ },
+ "material_flow": {
+ "default_value": 99
+ },
+ "speed_travel_layer_0": {
+ "value": "75.0"
+ },
+ "raft_base_acceleration": {
+ "value": "250"
+ },
+ "retraction_count_max": {
+ "default_value": 40
+ },
+ "ooze_shield_dist": {
+ "default_value": 4
+ },
+ "acceleration_support": {
+ "value": "250"
+ },
+ "max_skin_angle_for_expansion": {
+ "default_value": 50
+ },
+ "coasting_enable": {
+ "default_value": true
+ },
+ "brim_width": {
+ "default_value": 10
+ },
+ "acceleration_support_infill": {
+ "value": "250"
+ },
+ "retraction_prime_speed": {
+ "value": "30"
+ },
+ "raft_base_speed": {
+ "value": "35"
+ },
+ "acceleration_wall_0": {
+ "value": "250"
+ },
+ "xy_offset": {
+ "default_value": -0.16
+ },
+ "prime_tower_size": {
+ "default_value": 1
+ },
+ "jerk_ironing": {
+ "value": "5"
+ },
+ "switch_extruder_prime_speed": {
+ "value": "30"
+ },
+ "raft_jerk": {
+ "value": "5"
+ },
+ "top_skin_preshrink": {
+ "value": "1.2000000000000002"
+ },
+ "material_print_temperature": {
+ "value": "195"
+ },
+ "wall_material_flow": {
+ "value": "99"
+ },
+ "jerk_roofing": {
+ "value": "5"
+ },
+ "cool_fan_full_at_height": {
+ "value": "0"
+ },
+ "acceleration_wall_x": {
+ "value": "250"
+ },
+ "support_bottom_distance": {
+ "value": "0.23"
+ },
+ "cool_min_speed": {
+ "default_value": 15
+ },
+ "default_material_bed_temperature": {
+ "default_value": 50
+ },
+ "raft_interface_thickness": {
+ "value": "0.2"
+ }
+ }
+}
diff --git a/resources/definitions/stereotech_start.def.json b/resources/definitions/stereotech_start.def.json
new file mode 100644
index 0000000000..e85893d811
--- /dev/null
+++ b/resources/definitions/stereotech_start.def.json
@@ -0,0 +1,45 @@
+{
+ "version": 2,
+ "name": "Stereotech START",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Stereotech",
+ "manufacturer": "Stereotech LLC.",
+ "file_formats": "text/x-gcode",
+ "platform": "stereotech_start.stl",
+ "icon": "icon_ultimaker2",
+ "platform_offset": [0, 0, 0],
+ "machine_extruder_trains":
+ {
+ "0": "stereotech_start_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_width": {
+ "default_value": 190
+ },
+ "machine_height": {
+ "default_value": 190
+ },
+ "machine_depth": {
+ "default_value": 190
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;Home all axes (max endstops)\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG28 ;Home all axes (max endstops)\nM84 ;steppers off\nG90 ;absolute positioning"
+ },
+ "machine_shape": {
+ "default_value": "rectangular"
+ }
+ }
+}
diff --git a/resources/definitions/stereotech_ste320.def.json b/resources/definitions/stereotech_ste320.def.json
new file mode 100644
index 0000000000..3eb114324b
--- /dev/null
+++ b/resources/definitions/stereotech_ste320.def.json
@@ -0,0 +1,89 @@
+{
+ "version": 2,
+ "name": "Stereotech STE320",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Stereotech",
+ "manufacturer": "Stereotech LLC.",
+ "category": "Other",
+ "platform": "stereotech_ste320_platform.obj",
+ "platform_texture": "StereotechSte320backplate.png",
+ "platform_offset": [
+ 0,
+ 0,
+ -14
+ ],
+ "file_formats": "text/x-gcode",
+ "has_materials": true,
+ "supports_usb_connection": false,
+ "machine_extruder_trains": {
+ "0": "stereotech_ste320_1st",
+ "1": "stereotech_ste320_2nd"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Stereotech STE320"
+ },
+ "machine_width": {
+ "default_value": 218
+ },
+ "machine_height": {
+ "default_value": 200
+ },
+ "machine_depth": {
+ "default_value": 210
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [
+ -29,
+ 22
+ ],
+ [
+ -29,
+ -20
+ ],
+ [
+ 27,
+ 22
+ ],
+ [
+ 27,
+ -20
+ ]
+ ]
+ },
+ "gantry_height": {
+ "value": "25"
+ },
+ "machine_use_extruder_offset_to_offset_coords": {
+ "default_value": true
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;homing\nG1 Z15.0 F9000 ;move the platform down 15mm\nT1 ;Switch to the 2nd extruder\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 6 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F200 E-{switch_extruder_retraction_amount}\nT0 ;Switch to the 1st extruder\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 6 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 T0 S0 ;1st extruder heater off\nM104 T1 S0 ;2nd extruder heater off\nM140 S0 ;heated bed heater off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ },
+ "prime_tower_position_x": {
+ "value": "195"
+ },
+ "prime_tower_position_y": {
+ "value": "149"
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/strateo3d.def.json b/resources/definitions/strateo3d.def.json
new file mode 100644
index 0000000000..2ee3650404
--- /dev/null
+++ b/resources/definitions/strateo3d.def.json
@@ -0,0 +1,138 @@
+{
+ "version": 2,
+ "name": "Strateo3D",
+ "inherits": "fdmprinter",
+ "metadata":
+ {
+ "author": "M.K",
+ "manufacturer": "eMotionTech",
+ "category": "Other",
+ "visible": true,
+ "file_formats": "text/x-gcode",
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variants": true,
+ "preferred_variant_name": "Standard 0.6",
+ "preferred_material": "emotiontech_pla",
+ "preferred_quality_type": "c",
+ "variants_name": "Print Head",
+ "machine_extruder_trains":
+ {
+ "0": "strateo3d_right_extruder",
+ "1": "strateo3d_left_extruder"
+ }
+ },
+
+ "overrides":
+ {
+ "machine_name": { "default_value": "Strateo3D" },
+ "machine_width": { "default_value": 600 },
+ "machine_depth": { "default_value": 420 },
+ "machine_height": { "default_value": 495 },
+ "machine_heated_bed": { "default_value": true },
+ "machine_heated_build_volume": { "default_value": true },
+ "machine_center_is_zero": { "default_value": false },
+ "machine_head_with_fans_polygon": { "default_value": [ [ -76, -51.8 ] , [ 25, -51.8 ] , [ 25, 38.2 ] , [ -76, 38.2 ] ] },
+ "gantry_height": { "value": "40" },
+ "machine_extruder_count": { "default_value": 2 },
+ "machine_gcode_flavor": { "default_value": "Marlin" },
+ "machine_start_gcode": { "default_value": "G28 \nG90 G1 X300 Y210 Z15 F6000 \nG92 E0" },
+ "machine_end_gcode": { "default_value": "T1 \nM104 S0 \nT0 \nM104 S0 \nM140 S0 \nM141 S0 \nG91 \nG0 z1 \nG90 \nG28 \nM801.0 \nM84 \nM192" },
+ "extruder_prime_pos_y": {"minimum_value": "0", "maximum_value": "machine_depth"},
+ "extruder_prime_pos_x": {"minimum_value": "0", "maximum_value": "machine_width"},
+ "machine_heat_zone_length": { "default_value": 7 },
+ "default_material_print_temperature": { "maximum_value_warning": "350" },
+ "material_print_temperature": { "maximum_value_warning": "350" },
+ "material_print_temperature_layer_0": { "maximum_value_warning": "350" },
+ "material_bed_temperature": { "maximum_value": "130" },
+ "material_bed_temperature_layer_0": { "maximum_value": "130" },
+ "extruder_prime_pos_abs": { "default_value": true },
+ "machine_acceleration": { "default_value": 1500 },
+
+ "acceleration_enabled": { "value": false },
+ "acceleration_print": { "value": "machine_acceleration" },
+ "acceleration_wall": { "value": "math.ceil(acceleration_print * 1250 / acceleration_print)" },
+ "acceleration_wall_0": { "value": "math.ceil(acceleration_print * 1000 / acceleration_print)" },
+ "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 1250 / acceleration_print)" },
+ "acceleration_support": { "value": "acceleration_print" },
+ "acceleration_support_interface": { "value": "acceleration_topbottom" },
+ "acceleration_travel": { "value": "acceleration_print" },
+ "acceleration_layer_0": { "value": "acceleration_topbottom" },
+ "adaptive_layer_height_variation": { "default_value": 0.1 },
+ "adaptive_layer_height_variation_step": { "default_value": 0.05 },
+ "adhesion_type": { "default_value": "skirt" },
+ "expand_skins_expand_distance": { "value": "wall_line_width_0 + wall_line_count * wall_line_width_x" },
+ "gradual_infill_step_height": { "value": "layer_height*10" },
+ "gradual_support_infill_step_height": { "value": "layer_height*7" },
+ "infill_before_walls": { "default_value": false },
+ "infill_overlap": { "value": "0" },
+ "infill_wipe_dist": { "value": "0" },
+ "jerk_enabled": { "value": "False" },
+ "jerk_layer_0": { "value": "jerk_topbottom" },
+ "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" },
+ "jerk_print": { "value": "25" },
+ "jerk_support": { "value": "math.ceil(jerk_print * 15 / 25)" },
+ "jerk_support_interface": { "value": "jerk_topbottom" },
+ "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" },
+ "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" },
+ "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" },
+ "layer_start_x": { "value": "sum(extruderValues('machine_extruder_start_pos_x')) / len(extruderValues('machine_extruder_start_pos_x'))" },
+ "layer_start_y": { "value": "sum(extruderValues('machine_extruder_start_pos_y')) / len(extruderValues('machine_extruder_start_pos_y'))" },
+ "machine_min_cool_heat_time_window": { "value": "15" },
+ "machine_nozzle_cool_down_speed": { "default_value": 0.50 },
+ "machine_nozzle_heat_up_speed": { "default_value": 2.25 },
+ "material_final_print_temperature": { "value": "material_print_temperature - 10" },
+ "material_flow": { "default_value": 93 },
+ "material_flow_layer_0": { "value": "math.ceil(material_flow*1)" },
+ "material_initial_print_temperature": { "value": "material_print_temperature - 5" },
+ "meshfix_maximum_resolution": { "value": "0.03" },
+ "optimize_wall_printing_order": { "value": "True" },
+ "prime_blob_enable": { "enabled": false, "default_value": false },
+ "prime_tower_min_volume": { "default_value": 35 },
+ "prime_tower_position_x": { "value": "machine_width/2 - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1" },
+ "prime_tower_position_y": { "value": "machine_depth - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1" },
+ "retraction_amount": { "default_value": 1.5 },
+ "retraction_combing": { "default_value": "all" },
+ "retraction_combing_max_distance": { "default_value": 5 },
+ "retraction_count_max": { "default_value": 15 },
+ "retraction_hop": { "value": "2" },
+ "retraction_hop_enabled": { "value": "extruders_enabled_count > 1" },
+ "retraction_hop_only_when_collides": { "value": "True" },
+ "retraction_min_travel": { "value": "3*line_width" },
+ "retraction_prime_speed": { "value": "retraction_speed-10" },
+ "retraction_speed": { "default_value": 25 },
+ "skin_overlap": { "value": "10" },
+ "skirt_brim_minimal_length": { "default_value": 333 },
+ "speed_layer_0": { "value": "20" },
+ "speed_travel_layer_0": { "value": "100" },
+ "speed_prime_tower": { "value": "speed_topbottom" },
+ "speed_print": { "value": "50" },
+ "speed_support": { "value": "speed_wall" },
+ "speed_support_interface": { "value": "speed_topbottom" },
+ "speed_topbottom": { "value": "math.ceil(speed_print * 20/35)" },
+ "speed_travel": { "value": "150" },
+ "speed_wall": { "value": "math.ceil(speed_print * 3/4)" },
+ "speed_wall_0": { "value": "math.ceil(speed_wall * 2/3)" },
+ "speed_wall_x": { "value": "speed_wall" },
+ "support_angle": { "value": "50" },
+ "support_bottom_distance": {"value": "extruderValue(support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr, 'support_z_distance/2') if support_type == 'everywhere' else 0", "maximum_value_warning": "machine_nozzle_size*1.5" },
+ "support_interface_enable": { "default_value": true },
+ "support_interface_height": { "value": "layer_height*3" },
+ "support_interface_offset": { "value": "support_offset" },
+ "support_top_distance": {"value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance')", "maximum_value_warning": "machine_nozzle_size*1.5" },
+ "support_use_towers": { "default_value": true },
+ "support_xy_distance": { "value": "line_width * 1.7" },
+ "support_xy_distance_overhang": { "value": "wall_line_width_0" },
+ "support_z_distance": { "value": "layer_height*2", "maximum_value_warning": "machine_nozzle_size*1.5" },
+ "switch_extruder_prime_speed": { "value": "retraction_prime_speed" },
+ "switch_extruder_retraction_amount": { "value": "7" },
+ "switch_extruder_retraction_speeds": {"value": "retraction_retract_speed"},
+ "top_bottom_thickness": { "value": "3*layer_height", "minimum_value_warning": "layer_height*2" },
+ "top_thickness": { "value": "top_bottom_thickness" },
+ "top_layers": { "value": "0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))"},
+ "bottom_thickness": { "value": "top_bottom_thickness-2*layer_height+layer_height_0" },
+ "bottom_layers": { "value": "999999 if infill_sparse_density == 100 else math.ceil(round(((bottom_thickness-resolveOrValue('layer_height_0')) / resolveOrValue('layer_height'))+1, 4))"},
+ "travel_avoid_distance": { "value": "3 if extruders_enabled_count > 1 else machine_nozzle_tip_outer_diameter / 2 * 1.5" },
+ "wall_thickness": { "value": "wall_line_width_0 + wall_line_width_x" }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/structur3d_discov3ry1_complete_um2plus.def.json b/resources/definitions/structur3d_discov3ry1_complete_um2plus.def.json
index 2875b949be..e4893cacac 100644
--- a/resources/definitions/structur3d_discov3ry1_complete_um2plus.def.json
+++ b/resources/definitions/structur3d_discov3ry1_complete_um2plus.def.json
@@ -1,12 +1,11 @@
{
"version": 2,
- "name": "Discov3ry Complete (Ultimaker 2+)",
+ "name": "Discov3ry Complete",
"inherits": "fdmprinter",
"metadata": {
"author": "Andrew Finkle, CTO",
"manufacturer": "Structur3d.io",
"visible": true,
- "weight": 1,
"file_formats": "text/x-gcode",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2Plusbackplate.png",
@@ -15,9 +14,7 @@
"has_variants": true,
"variants_name": "Print core",
"preferred_variant_name": "0.84mm (Green)",
- "has_machine_materials": true,
"preferred_material": "structur3d_dap100silicone",
- "has_variant_materials": false,
"has_machine_quality": false,
"preferred_quality_type": "extra_fast",
"first_start_actions": [],
@@ -58,9 +55,6 @@
"line_width": {
"value": "round(machine_nozzle_size * 0.875, 2)"
},
- "speed_layer_0": {
- "default_value": 10
- },
"speed_support": {
"value": "speed_wall_0"
},
@@ -77,7 +71,7 @@
"default_value": true
},
"gantry_height": {
- "default_value": 52
+ "value": "52"
},
"machine_nozzle_head_distance": {
"default_value": 5
diff --git a/resources/definitions/tam.def.json b/resources/definitions/tam.def.json
index 0ed8d657a2..211049ca3d 100644
--- a/resources/definitions/tam.def.json
+++ b/resources/definitions/tam.def.json
@@ -1,6 +1,6 @@
{
"version": 2,
- "name": "Type A Machines Series 1 2014",
+ "name": "Series 1 2014",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
@@ -32,12 +32,11 @@
"machine_heated_bed": { "default_value": true },
"machine_head_with_fans_polygon": { "default_value": [ [ -35, 65 ], [ -35, -55 ], [ 55, 65 ], [ 55, -55 ] ] },
- "gantry_height": { "default_value": 35 },
- "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "gantry_height": { "value": "35" },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_center_is_zero": { "default_value": false },
"speed_print": { "default_value": 60 },
- "speed_travel": { "default_value": 200 },
"retraction_amount": { "default_value": 0.4 },
"retraction_speed": { "default_value": 35},
diff --git a/resources/definitions/tevo_blackwidow.def.json b/resources/definitions/tevo_blackwidow.def.json
index 25e7a2620d..9e450067fb 100644
--- a/resources/definitions/tevo_blackwidow.def.json
+++ b/resources/definitions/tevo_blackwidow.def.json
@@ -44,7 +44,7 @@
},
"gantry_height":
{
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor":
{
diff --git a/resources/definitions/tevo_tarantula.def.json b/resources/definitions/tevo_tarantula.def.json
index ec4ae667d5..f4bf2b901e 100644
--- a/resources/definitions/tevo_tarantula.def.json
+++ b/resources/definitions/tevo_tarantula.def.json
@@ -23,7 +23,7 @@
"machine_height": { "default_value": 200 },
"machine_depth": { "default_value": 200 },
"machine_center_is_zero": { "default_value": false },
- "machine_head_polygon":
+ "machine_head_with_fans_polygon":
{
"default_value":
[
@@ -33,7 +33,7 @@
[18, -18]
]
},
- "gantry_height": { "default_value": 55 },
+ "gantry_height": { "value": "55" },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_acceleration": { "default_value": 2650 },
"machine_max_jerk_xy": { "default_value": 15.0 },
diff --git a/resources/definitions/tevo_tornado.def.json b/resources/definitions/tevo_tornado.def.json
index 9110e4ba4d..3b6c431feb 100644
--- a/resources/definitions/tevo_tornado.def.json
+++ b/resources/definitions/tevo_tornado.def.json
@@ -13,7 +13,7 @@
}
},
"overrides": {
- "machine_name": {
+ "machine_name": {
"default_value": "Tevo Tornado"
},
"machine_width": {
@@ -25,10 +25,10 @@
"machine_depth": {
"default_value": 300
},
- "machine_center_is_zero": {
- "default_value": false
+ "machine_center_is_zero": {
+ "default_value": false
},
- "machine_head_polygon": {
+ "machine_head_with_fans_polygon": {
"default_value": [
[-30, 34],
[-30, -32],
@@ -70,21 +70,39 @@
"default_value": true
},
"gantry_height": {
- "default_value": 30
+ "value": "30"
},
"acceleration_enabled": {
- "default_value": false
+ "default_value": true
},
- "machine_acceleration": {
- "default_value": 1500
+ "acceleration_print": {
+ "default_value": 500
+ },
+ "acceleration_travel": {
+ "value": 500
+ },
+ "acceleration_travel_layer_0": {
+ "value": 500
+ },
+ "machine_acceleration": {
+ "default_value": 1500
},
"jerk_enabled": {
- "default_value": false
+ "default_value": true
},
- "machine_max_jerk_xy": {
- "default_value": 6
+ "jerk_print": {
+ "default_value": 8
},
- "machine_gcode_flavor": {
+ "jerk_travel": {
+ "value": 8
+ },
+ "jerk_travel_layer_0": {
+ "value": 8
+ },
+ "machine_max_jerk_xy": {
+ "default_value": 6
+ },
+ "machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
diff --git a/resources/definitions/tizyx_evy.def.json b/resources/definitions/tizyx_evy.def.json
index fe9a02a31c..57c7337196 100644
--- a/resources/definitions/tizyx_evy.def.json
+++ b/resources/definitions/tizyx_evy.def.json
@@ -10,13 +10,12 @@
"has_machine_quality": true,
"has_materials": true,
- "has_machine_materials": true,
"has_variants": true,
"preferred_variant_name": "0.4mm",
"preferred_material": "tizyx_pla",
"preferred_quality_type": "normal",
- "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175","generic_pp", "generic_pva", "generic_pva_175", "generic_tpu", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ],
+ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175","generic_pp", "generic_pva", "generic_pva_175", "generic_tpu", "generic_tpu_175", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ],
"machine_extruder_trains":
{
@@ -32,7 +31,7 @@
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
- "gantry_height": { "default_value": 500 },
+ "gantry_height": { "value": "500" },
"machine_height": { "default_value": 255 },
"machine_depth": { "default_value": 255 },
"machine_width": { "default_value": 255 },
@@ -51,13 +50,8 @@
"fill_outline_gaps": { "default_value": true},
"infill_sparse_density": { "default_value": 15},
"retraction_amount": { "default_value": 2.5},
- "retraction_min_travel": { "default_value": 2},
"retraction_speed": { "default_value": 30},
"speed_print": { "default_value": 60},
- "speed_topbottom": { "default_value": 50},
- "speed_wall_0": { "default_value": 40},
- "top_layers": { "default_value": 4},
- "wall_line_count": { "default_value": 2},
"cool_min_layer_time": { "default_value": 11},
"layer_height": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
"layer_height_0": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
@@ -69,6 +63,13 @@
"machine_end_gcode":
{
"default_value": "M104 S0\nM140 S0\nG91\nG1 E-5 F300\nG1 Z+3 F3000\nG1 Y245 F3000\nM84"
- }
+ },
+
+ "acceleration_enabled": {"value": "False"},
+ "acceleration_print": {"value": "1500"},
+ "z_seam_type": {"default_value": "back"},
+ "z_seam_x": {"value": "127.5"},
+ "z_seam_y": {"value": "250"},
+ "retraction_combing": {"default_value": "off"}
}
}
diff --git a/resources/definitions/tizyx_evy_dual.def.json b/resources/definitions/tizyx_evy_dual.def.json
new file mode 100644
index 0000000000..e06894139e
--- /dev/null
+++ b/resources/definitions/tizyx_evy_dual.def.json
@@ -0,0 +1,63 @@
+{
+ "name": "TiZYX EVY Dual",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "TiZYX",
+ "manufacturer": "TiZYX",
+ "file_formats": "text/x-gcode",
+
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variants": true,
+ "preferred_variant_name": "Classic Extruder",
+
+ "preferred_material": "tizyx_pla",
+ "preferred_quality_type": "normal",
+ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_cpe_175", "generic_cpe_plus","generic_hips_175","generic_nylon_175", "generic_pc_175", "generic_pva_175", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ],
+
+ "machine_extruder_trains":
+ {
+ "0": "tizyx_evy_dual_extruder_0",
+ "1": "tizyx_evy_dual_extruder_1"
+ },
+ "platform": "tizyx_k25_platform.stl",
+ "platform_offset": [0, -4, 0],
+ "first_start_actions": ["MachineSettingsAction"],
+ "supported_actions": ["MachineSettingsAction"]
+ },
+
+ "overrides": {
+ "machine_extruder_count": { "default_value": 2 },
+ "machine_heated_bed": { "default_value": true },
+ "machine_center_is_zero": { "default_value": false },
+ "gantry_height": { "value": "500" },
+ "machine_height": { "default_value": 255 },
+ "machine_depth": { "default_value": 255 },
+ "machine_width": { "default_value": 255 },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [25, 49],
+ [25, -49],
+ [-25, -49],
+ [25, 49]
+ ]
+ },
+ "machine_start_gcode":
+ {
+ "default_value": "M82\nG90\nG28 X\nG28 Y\nG28 Z\nG29\nG91\nG1 Z0\nG90\nM82\nG92 E0\nG1 X125 Y245 F3000\nG1 Z0"
+ },
+ "machine_end_gcode":
+ {
+ "default_value": "M104 S0\nM140 S0\nG91\nG1 E-5 F300\nG1 Z+3 F3000\nG1 Y245 F3000\nM84"
+ },
+
+ "acceleration_enabled": {"value": "False"},
+ "acceleration_print": {"value": "1500"},
+ "z_seam_type": {"default_value": "back"},
+ "z_seam_x": {"value": "127.5"},
+ "z_seam_y": {"value": "250"},
+ "retraction_combing": {"default_value": "off"}
+ }
+}
diff --git a/resources/definitions/tizyx_k25.def.json b/resources/definitions/tizyx_k25.def.json
index d6a5ff5ecd..32fa9b331d 100644
--- a/resources/definitions/tizyx_k25.def.json
+++ b/resources/definitions/tizyx_k25.def.json
@@ -1,52 +1,60 @@
-{
- "version": 2,
- "name": "TiZYX K25",
- "inherits": "fdmprinter",
- "metadata":
- {
- "visible": true,
- "author": "TiZYX",
- "manufacturer": "TiZYX",
- "file_formats": "text/x-gcode",
- "platform": "tizyx_k25_platform.stl",
- "platform_offset": [0, -4, 0],
- "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pla", "generic_pla_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ],
- "preferred_material": "tizyx_pla",
- "has_machine_quality": true,
- "has_materials": true,
- "has_variants": true,
- "preferred_variant_name": "0.4 mm",
- "machine_extruder_trains":
- {
- "0": "tizyx_k25_extruder_0"
- }
- },
-
- "overrides":
- {
- "machine_name": { "default_value": "TiZYX K25" },
- "machine_heated_bed": { "default_value": true },
- "machine_width": { "default_value": 255 },
- "machine_height": { "default_value": 255 },
- "machine_depth": { "default_value": 255 },
- "machine_center_is_zero": { "default_value": false },
- "gantry_height": { "default_value": 500 },
- "machine_head_with_fans_polygon": {
- "default_value": [
- [25, 49],
- [25, -49],
- [-25, -49],
- [25, 49]
- ]
- },
- "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
- "machine_start_gcode":
- {
- "default_value": "M82\nG90\nG28 X\nG28 Y\nG28 Z\nG29\nG91\nG1 Z0\nG90\nM82\nG92 E0\nG1 X125 Y245 F3000\nG1 Z0"
- },
- "machine_end_gcode":
- {
- "default_value": "M104 S0\nM140 S0\nG91\nG1 E-5 F300\nG1 Z+3 F3000\nG1 Y245 F3000\nM84"
- }
- }
-}
+{
+ "version": 2,
+ "name": "TiZYX K25",
+ "inherits": "fdmprinter",
+ "metadata":
+ {
+ "visible": true,
+ "author": "TiZYX",
+ "manufacturer": "TiZYX",
+ "file_formats": "text/x-gcode",
+ "platform": "tizyx_k25_platform.stl",
+ "platform_offset": [0, -4, 0],
+ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pla", "generic_pla_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "generic_tpu_175", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ],
+ "preferred_material": "tizyx_pla",
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variants": true,
+ "preferred_variant_name": "0.4 mm",
+ "machine_extruder_trains":
+ {
+ "0": "tizyx_k25_extruder_0"
+ }
+ },
+
+ "overrides":
+ {
+ "machine_name": { "default_value": "TiZYX K25" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 255 },
+ "machine_height": { "default_value": 255 },
+ "machine_depth": { "default_value": 255 },
+ "machine_center_is_zero": { "default_value": false },
+ "gantry_height": { "value": "500" },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [25, 49],
+ [25, -49],
+ [-25, -49],
+ [25, 49]
+ ]
+ },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode":
+ {
+ "default_value": "M82\nG90\nG28 X\nG28 Y\nG28 Z\nG29\nG91\nG1 Z0\nG90\nM82\nG92 E0\nG1 X125 Y245 F3000\nG1 Z0"
+ },
+ "machine_end_gcode":
+ {
+ "default_value": "M104 S0\nM140 S0\nG91\nG1 E-5 F300\nG1 Z+3 F3000\nG1 Y245 F3000\nM84"
+ },
+
+
+ "acceleration_enabled": {"value": "False"},
+ "acceleration_print": {"value": "1500"},
+ "z_seam_type": {"default_value": "back"},
+ "z_seam_x": {"value": "127.5"},
+ "z_seam_y": {"value": "250"},
+ "retraction_combing": {"default_value": "off"}
+ }
+}
diff --git a/resources/definitions/ubuild-3d_mr_bot_280.def.json b/resources/definitions/ubuild-3d_mr_bot_280.def.json
index 7eb65c3e78..255d8f032b 100644
--- a/resources/definitions/ubuild-3d_mr_bot_280.def.json
+++ b/resources/definitions/ubuild-3d_mr_bot_280.def.json
@@ -1,5 +1,4 @@
{
- "id": "ubuild-3d_mr_bot_280",
"version": 2,
"name": "uBuild-3D Mr Bot 280",
"inherits": "fdmprinter",
@@ -24,17 +23,14 @@
"machine_height": { "default_value": 275 },
"machine_depth": { "default_value": 275 },
"machine_center_is_zero": { "default_value": false },
- "material_bed_temperature": { "default_value": 70 },
"layer_height_0": { "default_value": 0.1 },
"retraction_amount": { "default_value": 2 },
"retraction_speed": { "default_value": 50 },
- "retraction_retract_speed": { "default_value": 50 },
- "retraction_prime_speed": { "default_value": 30 },
"adhesion_type": { "default_value": "skirt" },
"machine_nozzle_heat_up_speed": { "default_value": 2 },
"machine_nozzle_cool_down_speed": { "default_value": 2 },
"machine_head_with_fans_polygon": { "default_value": [[-20,20],[10,10],[10,10],[10,10]] },
- "gantry_height": { "default_value": 275 },
+ "gantry_height": { "value": "275" },
"machine_max_feedrate_z": { "default_value": 15 },
"machine_max_feedrate_e": { "default_value": 60 },
"machine_max_acceleration_z": { "default_value": 1000 },
diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json
index 4cc291ff45..40fbdaf709 100644
--- a/resources/definitions/ultimaker2.def.json
+++ b/resources/definitions/ultimaker2.def.json
@@ -14,9 +14,6 @@
"has_materials": false,
"has_machine_quality": true,
"preferred_variant_name": "0.4 mm",
- "exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white"],
- "first_start_actions": ["UM2UpgradeSelection"],
- "supported_actions":["UM2UpgradeSelection"],
"machine_extruder_trains":
{
"0": "ultimaker2_extruder_0"
@@ -56,7 +53,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 48
+ "value": "48"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
@@ -91,9 +88,6 @@
},
"machine_acceleration": {
"default_value": 3000
- },
- "machine_nozzle_temp_enabled": {
- "default_value": false
}
}
}
diff --git a/resources/definitions/ultimaker2_extended_olsson.def.json b/resources/definitions/ultimaker2_extended_olsson.def.json
new file mode 100644
index 0000000000..d2eb7f9a5d
--- /dev/null
+++ b/resources/definitions/ultimaker2_extended_olsson.def.json
@@ -0,0 +1,12 @@
+{
+ "version": 2,
+ "name": "Ultimaker 2 Extended with Olsson",
+ "inherits": "ultimaker2_extended",
+ "metadata": {
+ "has_variants": true
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Ultimaker 2 Extended with Olsson" }
+ }
+}
diff --git a/resources/definitions/ultimaker2_go.def.json b/resources/definitions/ultimaker2_go.def.json
index 9e374b2c88..774d215bef 100644
--- a/resources/definitions/ultimaker2_go.def.json
+++ b/resources/definitions/ultimaker2_go.def.json
@@ -11,7 +11,6 @@
"platform": "ultimaker2go_platform.obj",
"platform_texture": "Ultimaker2Gobackplate.png",
"platform_offset": [0, 0, 0],
- "first_start_actions": [],
"machine_extruder_trains":
{
"0": "ultimaker2_go_extruder_0"
diff --git a/resources/definitions/ultimaker2_olsson.def.json b/resources/definitions/ultimaker2_olsson.def.json
new file mode 100644
index 0000000000..2f8b877942
--- /dev/null
+++ b/resources/definitions/ultimaker2_olsson.def.json
@@ -0,0 +1,13 @@
+{
+ "version": 2,
+ "name": "Ultimaker 2 with Olsson Block",
+ "inherits": "ultimaker2",
+ "metadata": {
+ "has_variants": true,
+ "quality_definition": "ultimaker2"
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Ultimaker 2 with Olsson Block" }
+ }
+}
diff --git a/resources/definitions/ultimaker2_plus.def.json b/resources/definitions/ultimaker2_plus.def.json
index 28fd2b71f9..633e50bdba 100644
--- a/resources/definitions/ultimaker2_plus.def.json
+++ b/resources/definitions/ultimaker2_plus.def.json
@@ -12,8 +12,8 @@
"preferred_variant_name": "0.4 mm",
"has_variants": true,
"has_materials": true,
- "has_machine_materials": true,
"has_machine_quality": true,
+ "exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "generic_cffcpe", "generic_cffpa", "generic_gffcpe", "generic_gffpa", "structur3d_dap100silicone" ],
"first_start_actions": [],
"supported_actions": [],
"machine_extruder_trains":
@@ -37,9 +37,6 @@
"line_width": {
"value": "round(machine_nozzle_size * 0.875, 2)"
},
- "speed_layer_0": {
- "default_value": 20
- },
"speed_support": {
"value": "speed_wall_0"
},
@@ -50,7 +47,7 @@
"default_value": true
},
"gantry_height": {
- "default_value": 52
+ "value": "52"
},
"machine_nozzle_head_distance": {
"default_value": 5
diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json
index 9e017688a2..b34ff3bdba 100644
--- a/resources/definitions/ultimaker3.def.json
+++ b/resources/definitions/ultimaker3.def.json
@@ -12,8 +12,8 @@
"platform_offset": [0, 0, 0],
"has_machine_quality": true,
"has_materials": true,
- "has_machine_materials": true,
"has_variants": true,
+ "exclude_materials": [ "generic_hips", "generic_petg", "generic_cffcpe", "generic_cffpa", "generic_gffcpe", "generic_gffpa", "structur3d_dap100silicone" ],
"preferred_variant_name": "AA 0.4",
"preferred_quality_type": "normal",
"variants_name": "Print core",
@@ -25,15 +25,18 @@
"first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ],
"supports_usb_connection": false,
+ "supports_network_connection": true,
"firmware_update_info": {
"id": 9066,
"check_urls":
[
- "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
- "http://software.ultimaker.com/releases/firmware/9066/stable/version.txt"
+ "https://software.ultimaker.com/releases/firmware/9066/stable/um-update.swu.version"
],
"update_url": "https://ultimaker.com/firmware"
- }
+ },
+ "bom_numbers": [
+ 9066
+ ]
},
@@ -62,7 +65,7 @@
"machine_max_feedrate_y": { "default_value": 300 },
"machine_max_feedrate_z": { "default_value": 40 },
"machine_acceleration": { "default_value": 3000 },
- "gantry_height": { "default_value": 60 },
+ "gantry_height": { "value": "60" },
"machine_disallowed_areas": { "default_value": [
[[92.8, -53.4], [92.8, -97.5], [116.5, -97.5], [116.5, -53.4]],
[[73.8, 107.5], [73.8, 100.5], [116.5, 100.5], [116.5, 107.5]],
@@ -78,7 +81,7 @@
"prime_tower_position_x": { "value": "machine_depth - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) - 30" },
"prime_tower_wipe_enabled": { "default_value": false },
- "prime_blob_enable": { "enabled": true, "default_value": true },
+ "prime_blob_enable": { "enabled": true, "default_value": true, "value": "resolveOrValue('print_sequence') != 'one_at_a_time'" },
"acceleration_enabled": { "value": "True" },
"acceleration_layer_0": { "value": "acceleration_topbottom" },
@@ -118,7 +121,6 @@
"material_bed_temperature": { "maximum_value": "115" },
"material_bed_temperature_layer_0": { "maximum_value": "115" },
"material_standby_temperature": { "value": "100" },
- "meshfix_maximum_resolution": { "value": "0.04" },
"multiple_mesh_overlap": { "value": "0" },
"optimize_wall_printing_order": { "value": "True" },
"prime_tower_enable": { "default_value": true },
diff --git a/resources/definitions/ultimaker3_extended.def.json b/resources/definitions/ultimaker3_extended.def.json
index 68f26969b7..ba9824896f 100644
--- a/resources/definitions/ultimaker3_extended.def.json
+++ b/resources/definitions/ultimaker3_extended.def.json
@@ -12,7 +12,6 @@
"platform_texture": "Ultimaker3Extendedbackplate.png",
"platform_offset": [0, 0, 0],
"has_machine_quality": true,
- "has_machine_materials": true,
"has_materials": true,
"has_variants": true,
"preferred_variant_name": "AA 0.4",
@@ -28,11 +27,13 @@
"id": 9511,
"check_urls":
[
- "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
- "http://software.ultimaker.com/releases/firmware/9511/stable/version.txt"
+ "https://software.ultimaker.com/releases/firmware/9066/stable/um-update.swu.version"
],
"update_url": "https://ultimaker.com/firmware"
- }
+ },
+ "bom_numbers": [
+ 9511
+ ]
},
"overrides": {
diff --git a/resources/definitions/ultimaker_original.def.json b/resources/definitions/ultimaker_original.def.json
index 6a978c47cb..71130312e7 100644
--- a/resources/definitions/ultimaker_original.def.json
+++ b/resources/definitions/ultimaker_original.def.json
@@ -11,9 +11,9 @@
"platform": "ultimaker_platform.stl",
"has_materials": true,
"has_machine_quality": true,
- "exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white"],
- "first_start_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
- "supported_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
+ "exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "generic_cffcpe", "generic_cffpa", "generic_gffcpe", "generic_gffpa", "structur3d_dap100silicone" ],
+ "first_start_actions": ["UMOUpgradeSelection", "BedLevel"],
+ "supported_actions": ["UMOUpgradeSelection", "BedLevel"],
"machine_extruder_trains":
{
"0": "ultimaker_original_extruder_0"
@@ -46,7 +46,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/ultimaker_original_dual.def.json b/resources/definitions/ultimaker_original_dual.def.json
index 999650aa28..fd9b91e238 100644
--- a/resources/definitions/ultimaker_original_dual.def.json
+++ b/resources/definitions/ultimaker_original_dual.def.json
@@ -12,7 +12,7 @@
"has_materials": true,
"has_machine_quality": true,
"quality_definition": "ultimaker_original",
- "exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white"],
+ "exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "generic_cffcpe", "generic_cffpa", "generic_gffcpe", "generic_gffpa", "structur3d_dap100silicone" ],
"machine_extruder_trains":
{
"0": "ultimaker_original_dual_1st",
@@ -20,8 +20,8 @@
},
"firmware_file": "MarlinUltimaker-{baudrate}-dual.hex",
"firmware_hbk_file": "MarlinUltimaker-HBK-{baudrate}-dual.hex",
- "first_start_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
- "supported_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"]
+ "first_start_actions": ["UMOUpgradeSelection", "BedLevel"],
+ "supported_actions": ["UMOUpgradeSelection", "BedLevel"]
},
"overrides": {
@@ -48,7 +48,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/ultimaker_original_plus.def.json b/resources/definitions/ultimaker_original_plus.def.json
index bdb8a3d788..949e2e8d0d 100644
--- a/resources/definitions/ultimaker_original_plus.def.json
+++ b/resources/definitions/ultimaker_original_plus.def.json
@@ -10,8 +10,8 @@
"platform": "ultimaker2_platform.obj",
"platform_texture": "UltimakerPlusbackplate.png",
"quality_definition": "ultimaker_original",
- "first_start_actions": ["UMOCheckup", "BedLevel"],
- "supported_actions": ["UMOCheckup", "BedLevel"],
+ "first_start_actions": ["BedLevel"],
+ "supported_actions": ["BedLevel"],
"machine_extruder_trains":
{
"0": "ultimaker_original_plus_extruder_0"
diff --git a/resources/definitions/ultimaker_s3.def.json b/resources/definitions/ultimaker_s3.def.json
new file mode 100644
index 0000000000..efdc7cca0a
--- /dev/null
+++ b/resources/definitions/ultimaker_s3.def.json
@@ -0,0 +1,165 @@
+{
+ "version": 2,
+ "name": "Ultimaker S3",
+ "inherits": "ultimaker",
+ "metadata": {
+ "author": "Ultimaker",
+ "manufacturer": "Ultimaker B.V.",
+ "category": "Ultimaker",
+ "visible": true,
+ "file_formats": "application/x-ufp;text/x-gcode",
+ "platform": "ultimaker_s3_platform.obj",
+ "platform_texture": "UltimakerS3backplate.png",
+ "platform_offset": [0, 0, 0],
+ "has_machine_quality": true,
+ "has_materials": true,
+ "has_variant_buildplates": false,
+ "has_variants": true,
+ "exclude_materials": [ "generic_hips", "generic_petg", "structur3d_dap100silicone" ],
+ "preferred_variant_name": "AA 0.4",
+ "preferred_quality_type": "normal",
+ "variants_name": "Print core",
+ "nozzle_offsetting_for_disallowed_areas": false,
+ "machine_extruder_trains":
+ {
+ "0": "ultimaker_s3_extruder_left",
+ "1": "ultimaker_s3_extruder_right"
+ },
+ "first_start_actions": [ "DiscoverUM3Action" ],
+ "supported_actions": [ "DiscoverUM3Action" ],
+ "supports_usb_connection": false,
+ "weight": -1,
+ "firmware_update_info": {
+ "id": 213482,
+ "check_urls": ["https://software.ultimaker.com/releases/firmware/213482/stable/um-update.swu.version"],
+ "update_url": "https://ultimaker.com/firmware"
+ },
+ "bom_numbers": [
+ 213482
+ ]
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Ultimaker S3" },
+ "machine_width": { "default_value": 230 },
+ "machine_depth": { "default_value": 190 },
+ "machine_height": { "default_value": 200 },
+ "machine_heated_bed": { "default_value": true },
+ "machine_nozzle_heat_up_speed": { "default_value": 1.4 },
+ "machine_nozzle_cool_down_speed": { "default_value": 0.8 },
+ "machine_head_with_fans_polygon":
+ {
+ "default_value":
+ [
+ [ -41.4, -45.8 ],
+ [ -41.4, 36.0 ],
+ [ 63.3, 36.0 ],
+ [ 63.3, -45.8 ]
+ ]
+ },
+ "machine_gcode_flavor": { "default_value": "Griffin" },
+ "machine_max_feedrate_x": { "default_value": 300 },
+ "machine_max_feedrate_y": { "default_value": 300 },
+ "machine_max_feedrate_z": { "default_value": 40 },
+ "machine_acceleration": { "default_value": 3000 },
+ "gantry_height": { "value": "60" },
+ "machine_extruder_count": { "default_value": 2 },
+ "extruder_prime_pos_abs": { "default_value": true },
+ "machine_start_gcode": { "default_value": "" },
+ "machine_end_gcode": { "default_value": "" },
+ "prime_blob_enable": { "enabled": true, "default_value": false },
+
+ "speed_travel":
+ {
+ "maximum_value": "150",
+ "value": "150"
+ },
+
+ "acceleration_enabled": { "value": "True" },
+ "acceleration_layer_0": { "value": "acceleration_topbottom" },
+ "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
+ "acceleration_print": { "value": "4000" },
+ "acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
+ "acceleration_support_interface": { "value": "acceleration_topbottom" },
+ "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 500 / 4000)" },
+ "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 4000)" },
+ "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 500 / 1000)" },
+ "brim_width": { "value": "3" },
+ "cool_fan_full_at_height": { "value": "layer_height_0 + 4 * layer_height" },
+ "cool_fan_speed": { "value": "50" },
+ "cool_fan_speed_max": { "value": "100" },
+ "cool_min_speed": { "value": "5" },
+ "infill_line_width": { "value": "round(line_width * 0.5 / 0.35, 2)" },
+ "infill_overlap": { "value": "0" },
+ "infill_pattern": { "value": "'triangles'" },
+ "infill_wipe_dist": { "value": "0" },
+ "jerk_enabled": { "value": "True" },
+ "jerk_layer_0": { "value": "jerk_topbottom" },
+ "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" },
+ "jerk_print": { "value": "25" },
+ "jerk_support": { "value": "math.ceil(jerk_print * 15 / 25)" },
+ "jerk_support_interface": { "value": "jerk_topbottom" },
+ "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" },
+ "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" },
+ "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" },
+ "layer_height_0": { "value": "round(machine_nozzle_size / 1.5, 2)" },
+ "layer_start_x": { "value": "sum(extruderValues('machine_extruder_start_pos_x')) / len(extruderValues('machine_extruder_start_pos_x'))" },
+ "layer_start_y": { "value": "sum(extruderValues('machine_extruder_start_pos_y')) / len(extruderValues('machine_extruder_start_pos_y'))" },
+ "line_width": { "value": "machine_nozzle_size * 0.875" },
+ "machine_min_cool_heat_time_window": { "value": "15" },
+ "default_material_print_temperature": { "value": "200" },
+ "material_standby_temperature": { "value": "100" },
+ "multiple_mesh_overlap": { "value": "0" },
+ "prime_tower_enable": { "value": "True" },
+ "raft_airgap": { "value": "0" },
+ "raft_base_speed": { "value": "20" },
+ "raft_base_thickness": { "value": "0.3" },
+ "raft_interface_line_spacing": { "value": "0.5" },
+ "raft_interface_line_width": { "value": "0.5" },
+ "raft_interface_speed": { "value": "20" },
+ "raft_interface_thickness": { "value": "0.2" },
+ "raft_jerk": { "value": "jerk_layer_0" },
+ "raft_margin": { "value": "10" },
+ "raft_speed": { "value": "25" },
+ "raft_surface_layers": { "value": "1" },
+ "retraction_amount": { "value": "6.5" },
+ "retraction_count_max": { "value": "10" },
+ "retraction_extrusion_window": { "value": "1" },
+ "retraction_hop": { "value": "2" },
+ "retraction_hop_enabled": { "value": "extruders_enabled_count > 1" },
+ "retraction_hop_only_when_collides": { "value": "True" },
+ "retraction_min_travel": { "value": "5" },
+ "retraction_prime_speed": { "value": "15" },
+ "skin_overlap": { "value": "10" },
+ "speed_equalize_flow_enabled": { "value": "True" },
+ "speed_layer_0": { "value": "20" },
+ "speed_prime_tower": { "value": "speed_topbottom" },
+ "speed_print": { "value": "35" },
+ "speed_support": { "value": "speed_wall_0" },
+ "speed_support_interface": { "value": "speed_topbottom" },
+ "speed_topbottom": { "value": "math.ceil(speed_print * 20 / 35)" },
+ "speed_wall": { "value": "math.ceil(speed_print * 30 / 35)" },
+ "speed_wall_0": { "value": "math.ceil(speed_wall * 20 / 30)" },
+ "speed_wall_x": { "value": "speed_wall" },
+ "support_angle": { "value": "45" },
+ "support_pattern": { "value": "'triangles'" },
+ "support_use_towers": { "value": "False" },
+ "support_xy_distance": { "value": "wall_line_width_0 * 2.5" },
+ "support_xy_distance_overhang": { "value": "wall_line_width_0" },
+ "support_z_distance": { "value": "0" },
+ "switch_extruder_prime_speed": { "value": "15" },
+ "switch_extruder_retraction_amount": { "value": "8" },
+ "top_bottom_thickness": { "value": "1" },
+ "travel_avoid_supports": { "value": "True" },
+ "travel_avoid_distance": { "value": "3 if extruders_enabled_count > 1 else machine_nozzle_tip_outer_diameter / 2 * 1.5" },
+ "wall_0_inset": { "value": "0" },
+ "wall_line_width_x": { "value": "round(line_width * 0.3 / 0.35, 2)" },
+ "wall_thickness": { "value": "1" },
+ "meshfix_maximum_resolution": { "value": "(speed_wall_0 + speed_wall_x) / 60" },
+ "meshfix_maximum_deviation": { "value": "layer_height / 2" },
+ "optimize_wall_printing_order": { "value": "True" },
+ "retraction_combing": { "default_value": "all" },
+ "initial_layer_line_width_factor": { "value": "120" },
+ "zig_zaggify_infill": { "value": "gradual_infill_steps == 0" }
+ }
+}
diff --git a/resources/definitions/ultimaker_s5.def.json b/resources/definitions/ultimaker_s5.def.json
index 310765dbc3..dcd44a371a 100644
--- a/resources/definitions/ultimaker_s5.def.json
+++ b/resources/definitions/ultimaker_s5.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_s5",
"version": 2,
"name": "Ultimaker S5",
"inherits": "ultimaker",
@@ -14,7 +13,6 @@
"platform_offset": [0, -30, -10],
"has_machine_quality": true,
"has_materials": true,
- "has_machine_materials": true,
"has_variant_buildplates": true,
"has_variants": true,
"preferred_variant_name": "AA 0.4",
@@ -30,12 +28,16 @@
"first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ],
"supports_usb_connection": false,
- "weight": -1,
+ "supports_network_connection": true,
+ "weight": -2,
"firmware_update_info": {
"id": 9051,
- "check_urls": ["http://software.ultimaker.com/releases/firmware/9051/stable/version.txt"],
+ "check_urls": ["https://software.ultimaker.com/releases/firmware/9051/stable/um-update.swu.version"],
"update_url": "https://ultimaker.com/firmware"
- }
+ },
+ "bom_numbers": [
+ 9051, 214475
+ ]
},
"overrides": {
@@ -44,6 +46,7 @@
"machine_depth": { "default_value": 240 },
"machine_height": { "default_value": 300 },
"machine_heated_bed": { "default_value": true },
+ "machine_heated_build_volume": { "default_value": true },
"machine_nozzle_heat_up_speed": { "default_value": 1.4 },
"machine_nozzle_cool_down_speed": { "default_value": 0.8 },
"machine_head_with_fans_polygon":
@@ -61,13 +64,11 @@
"machine_max_feedrate_y": { "default_value": 300 },
"machine_max_feedrate_z": { "default_value": 40 },
"machine_acceleration": { "default_value": 3000 },
- "gantry_height": { "default_value": 60 },
+ "gantry_height": { "value": "60" },
"machine_extruder_count": { "default_value": 2 },
"extruder_prime_pos_abs": { "default_value": true },
"machine_start_gcode": { "default_value": "" },
"machine_end_gcode": { "default_value": "" },
- "prime_tower_position_x": { "default_value": 345 },
- "prime_tower_position_y": { "default_value": 222.5 },
"prime_blob_enable": { "enabled": true, "default_value": false },
"speed_travel":
@@ -156,10 +157,12 @@
"wall_0_inset": { "value": "0" },
"wall_line_width_x": { "value": "round(line_width * 0.3 / 0.35, 2)" },
"wall_thickness": { "value": "1" },
- "meshfix_maximum_resolution": { "value": "0.04" },
+ "meshfix_maximum_resolution": { "value": "(speed_wall_0 + speed_wall_x) / 60" },
+ "meshfix_maximum_deviation": { "value": "layer_height / 2" },
"optimize_wall_printing_order": { "value": "True" },
"retraction_combing": { "default_value": "all" },
"initial_layer_line_width_factor": { "value": "120" },
- "zig_zaggify_infill": { "value": "gradual_infill_steps == 0" }
+ "zig_zaggify_infill": { "value": "gradual_infill_steps == 0" },
+ "build_volume_temperature": { "maximum_value": 50 }
}
}
diff --git a/resources/definitions/uni_print_3d.def.json b/resources/definitions/uni_print_3d.def.json
index 427177176a..99d9eab1e0 100644
--- a/resources/definitions/uni_print_3d.def.json
+++ b/resources/definitions/uni_print_3d.def.json
@@ -1,5 +1,4 @@
{
- "id": "uni_print_3d",
"name": "UNI-PRINT-3D",
"version": 2,
"inherits": "fdmprinter",
diff --git a/resources/definitions/uniqbot_one.def.json b/resources/definitions/uniqbot_one.def.json
index 5a33500b75..ec8336ae50 100644
--- a/resources/definitions/uniqbot_one.def.json
+++ b/resources/definitions/uniqbot_one.def.json
@@ -30,7 +30,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/vertex_delta_k8800.def.json b/resources/definitions/vertex_delta_k8800.def.json
index df24bd84fb..c92476da49 100644
--- a/resources/definitions/vertex_delta_k8800.def.json
+++ b/resources/definitions/vertex_delta_k8800.def.json
@@ -3,10 +3,10 @@
"version": 2,
"inherits": "fdmprinter",
"metadata": {
- "manufacturer": "Velleman nv",
+ "manufacturer": "Velleman N.V.",
"file_formats": "text/x-gcode",
"visible": true,
- "author": "Velleman",
+ "author": "Velleman N.V.",
"has_machine_quality": true,
"has_materials": true,
"machine_extruder_trains":
@@ -31,7 +31,7 @@
"default_value": "elliptic"
},
"gantry_height": {
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/vertex_k8400.def.json b/resources/definitions/vertex_k8400.def.json
index a3a3777547..bbeb8510ba 100644
--- a/resources/definitions/vertex_k8400.def.json
+++ b/resources/definitions/vertex_k8400.def.json
@@ -4,7 +4,7 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "manufacturer": "Velleman",
+ "manufacturer": "Velleman N.V.",
"file_formats": "text/x-gcode",
"platform": "Vertex_build_panel.stl",
"platform_offset": [0, -3, 0],
@@ -20,12 +20,6 @@
"machine_heated_bed": {
"default_value": true
},
- "material_bed_temperature": {
- "default_value": 0
- },
- "material_bed_temperature_layer_0": {
- "default_value": 0
- },
"machine_width": {
"default_value": 200
},
@@ -41,14 +35,6 @@
"machine_center_is_zero": {
"default_value": false
},
- "machine_head_polygon": {
- "default_value": [
- [-60, -18],
- [-60, 40],
- [18, 40],
- [18, -18]
- ]
- },
"machine_head_with_fans_polygon": {
"default_value": [
[-60, -40],
@@ -58,16 +44,16 @@
]
},
"gantry_height": {
- "default_value": 18
+ "value": "18"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
+ "default_value": "M104 T0 S{material_print_temperature_layer_0}\nG28 ;Home extruder\nG90 ;Absolute positioning\nM82 ;Extruder in absolute mode\nG1 Z1 F100\nG92 E0 ;Reset extruder position\nM109 T0 S{material_print_temperature_layer_0}\nG1 E20 F100\nG92 E0 ;Reset extruder position"
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
+ "default_value": "G1 X0 Y0 Z130 ;Get extruder out of way\nM107 ;Turn off fan\n;Disable all extruders\nG91 ;Relative positioning\nT0\nG1 E-1 ;Reduce filament pressure\nM104 T0 S0\nG90 ;Absolute positioning\nG92 E0 ;Reset extruder position\nM140 S0 ;Disable heated bed\nM84 ;Turn steppers off"
}
}
}
\ No newline at end of file
diff --git a/resources/definitions/vertex_k8400_dual.def.json b/resources/definitions/vertex_k8400_dual.def.json
index c7706135bd..498d550429 100644
--- a/resources/definitions/vertex_k8400_dual.def.json
+++ b/resources/definitions/vertex_k8400_dual.def.json
@@ -4,7 +4,7 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "manufacturer": "Velleman",
+ "manufacturer": "Velleman N.V.",
"file_formats": "text/x-gcode",
"platform": "Vertex_build_panel.stl",
"platform_offset": [0, -3, 0],
@@ -18,12 +18,6 @@
"machine_heated_bed": {
"default_value": true
},
- "material_bed_temperature": {
- "default_value": 0
- },
- "material_bed_temperature_layer_0": {
- "default_value": 0
- },
"machine_width": {
"default_value": 223.7
},
@@ -42,14 +36,6 @@
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
},
- "machine_head_polygon": {
- "default_value": [
- [-60, -18],
- [-60, 40],
- [18, 40],
- [18, -18]
- ]
- },
"machine_head_with_fans_polygon": {
"default_value": [
[-60, -40],
@@ -59,7 +45,7 @@
]
},
"gantry_height": {
- "default_value": 18
+ "value": "18"
},
"machine_extruder_count": {
"default_value": 2
diff --git a/resources/definitions/vertex_nano_k8600.def.json b/resources/definitions/vertex_nano_k8600.def.json
new file mode 100644
index 0000000000..ef9552caf3
--- /dev/null
+++ b/resources/definitions/vertex_nano_k8600.def.json
@@ -0,0 +1,77 @@
+{
+ "version": 2,
+ "name": "Vertex K8600",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "manufacturer": "Velleman N.V.",
+ "file_formats": "text/x-gcode",
+ "supports_usb_connection": true,
+ "supported_actions": ["MachineSettingsAction"],
+ "machine_extruder_trains": {
+ "0": "vertex_nano_k8600_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Vertex K8600"
+ },
+ "machine_heated_bed": {
+ "default_value": false
+ },
+ "machine_width": {
+ "default_value": 80
+ },
+ "machine_height": {
+ "default_value": 75
+ },
+ "machine_depth": {
+ "default_value": 80
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "; Vertex Nano Start G-code M0 is my nozzle clean M400 G28 ; Home extruder G90 ; Absolute positioning M82 ; Extruder in absolute mode M104 T0 S{material_print_temperature} G92 E0 ; Reset extruder position G1 Z1 F800 M109 T0 S{material_print_temperature} M117 Priming nozzle... M83 G1 E20 F100 ; purge/prime nozzle M82 G92 E0 ; Reset extruder position G4 S3 ; Wait 3 seconds G1 Z5 F2000 M117 Vertex Nano is printing"
+ },
+ "machine_end_gcode": {
+ "default_value": "; Vertex Nano end G-Code G91 ; Relative positioning T0 G1 E-1 F1500; Reduce filament pressure M104 T0 S0 G90 ; Absolute positioning G92 E0 ; Reset extruder position G28 M84 ; Turn steppers off"
+ },
+ "line_width": {
+ "value": 0.35
+ },
+ "infill_line_width": {
+ "value": 0.35
+ },
+ "wall_thickness": {
+ "value": 0.7
+ },
+ "top_bottom_thickness": {
+ "value": 0.6
+ },
+ "infill_sparse_density": {
+ "value": 40
+ },
+ "infill_overlap": {
+ "value": 5
+ },
+ "min_infill_area": {
+ "value": 0.1
+ },
+ "retract_at_layer_change": {
+ "value": true
+ },
+ "retraction_min_travel": {
+ "value": 1
+ },
+ "retraction_count_max": {
+ "value": 15
+ },
+ "retraction_extrusion_window": {
+ "value": 1
+ }
+ }
+}
diff --git a/resources/definitions/wanhao_d6.def.json b/resources/definitions/wanhao_d6.def.json
index c8a690d02c..eaaae54826 100644
--- a/resources/definitions/wanhao_d6.def.json
+++ b/resources/definitions/wanhao_d6.def.json
@@ -36,7 +36,7 @@
"default_value": true
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/wanhao_d9.def.json b/resources/definitions/wanhao_d9.def.json
index 39ad139ff8..ac4d41fa40 100644
--- a/resources/definitions/wanhao_d9.def.json
+++ b/resources/definitions/wanhao_d9.def.json
@@ -31,8 +31,6 @@
"support_angle": { "default_value": 60 },
"support_enable": { "default_value": true },
"layer_height_0": { "default_value": 0.15 },
- "top_thickness": { "default_value": 0.6 },
- "material_print_temperature": { "default_value": 190 },
"layer_height": { "default_value": 0.2 },
"speed_print": { "default_value": 30 },
"adhesion_type": { "default_value": "raft" },
diff --git a/resources/definitions/winbo_dragonl4.def.json b/resources/definitions/winbo_dragonl4.def.json
index 0ca68cdcee..bf52a785e9 100644
--- a/resources/definitions/winbo_dragonl4.def.json
+++ b/resources/definitions/winbo_dragonl4.def.json
@@ -37,7 +37,7 @@
"machine_max_feedrate_y": { "default_value": 300 },
"machine_max_feedrate_z": { "default_value": 40 },
"machine_acceleration": { "default_value": 2000 },
- "gantry_height": { "default_value": 80 },
+ "gantry_height": { "value": "80" },
"machine_extruder_count": { "default_value": 1 },
"machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nM9998\nG28 X0 Y0\nG28 Z0\nG1 F6000 Z0.3\nG92 E0\nG1 F800 X585 E12\nG92 E0" },
"machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" },
@@ -126,7 +126,7 @@
"support_bottom_height": { "value": "max((0.15 if(0.15%layer_height==0) else layer_height*int((0.15+layer_height)/layer_height)),layer_height)" },
"support_bottom_pattern": { "value": "'zigzag'" },
"support_connect_zigzags": { "value": "False" },
- "support_infill_rate": { "value": "8" },
+ "support_infill_rate": { "value": "8 if support_enable else 0 if support_tree_enable else 8" },
"support_interface_density": { "value": "80" },
"support_interface_enable": { "value": "True" },
"support_interface_height": { "value": "0.5" },
diff --git a/resources/definitions/winbo_mini2.def.json b/resources/definitions/winbo_mini2.def.json
index 7393fdf910..f1c94ca07e 100644
--- a/resources/definitions/winbo_mini2.def.json
+++ b/resources/definitions/winbo_mini2.def.json
@@ -37,7 +37,7 @@
"machine_max_feedrate_y": { "default_value": 200 },
"machine_max_feedrate_z": { "default_value": 40 },
"machine_acceleration": { "default_value": 3000 },
- "gantry_height": { "default_value": 75 },
+ "gantry_height": { "value": "75" },
"machine_extruder_count": { "default_value": 1 },
"machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 F1000 Z3\nG1 F4000 X0\nG1 F4000 Y0\nG1 F1000 Z0.2\nG92 E0\nG1 F1000 X30 E8\nG92 E0\nM117 Printing." },
"machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" },
@@ -126,7 +126,7 @@
"support_bottom_height": { "value": "max((0.15 if(0.15%layer_height==0) else layer_height*int((0.15+layer_height)/layer_height)),layer_height)" },
"support_bottom_pattern": { "value": "'zigzag'" },
"support_connect_zigzags": { "value": "False" },
- "support_infill_rate": { "value": "8" },
+ "support_infill_rate": { "value": "8 if support_enable else 0 if support_tree_enable else 8" },
"support_interface_density": { "value": "80" },
"support_interface_enable": { "value": "True" },
"support_interface_height": { "value": "0.5" },
diff --git a/resources/definitions/winbo_superhelper105.def.json b/resources/definitions/winbo_superhelper105.def.json
index 59e71fb446..ac78467a2a 100644
--- a/resources/definitions/winbo_superhelper105.def.json
+++ b/resources/definitions/winbo_superhelper105.def.json
@@ -37,7 +37,7 @@
"machine_max_feedrate_y": { "default_value": 200 },
"machine_max_feedrate_z": { "default_value": 40 },
"machine_acceleration": { "default_value": 2000 },
- "gantry_height": { "default_value": 200 },
+ "gantry_height": { "value": "200" },
"machine_extruder_count": { "default_value": 1 },
"machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 F6000 Z0.3\nG92 E0\nG1 F1000 X30 E8\nG92 E0\nM117 Printing." },
"machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" },
@@ -115,7 +115,7 @@
"support_bottom_height": { "value": "max((0.15 if(0.15%layer_height==0) else layer_height*int((0.15+layer_height)/layer_height)),layer_height)" },
"support_bottom_pattern": { "value": "'zigzag'" },
"support_connect_zigzags": { "value": "False" },
- "support_infill_rate": { "value": "8" },
+ "support_infill_rate": { "value": "8 if support_enable else 0 if support_tree_enable else 8" },
"support_interface_density": { "value": "80" },
"support_interface_enable": { "value": "True" },
"support_interface_height": { "value": "0.5" },
diff --git a/resources/definitions/z-bolt_classic.def.json b/resources/definitions/z-bolt_classic.def.json
index d294de473a..f9212c9597 100644
--- a/resources/definitions/z-bolt_classic.def.json
+++ b/resources/definitions/z-bolt_classic.def.json
@@ -41,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/z-bolt_plus.def.json b/resources/definitions/z-bolt_plus.def.json
index 57331df4c6..dace8ea300 100644
--- a/resources/definitions/z-bolt_plus.def.json
+++ b/resources/definitions/z-bolt_plus.def.json
@@ -41,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/zone3d_printer.def.json b/resources/definitions/zone3d_printer.def.json
index 328505e18a..4c72422788 100644
--- a/resources/definitions/zone3d_printer.def.json
+++ b/resources/definitions/zone3d_printer.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Ultimaker",
- "manufacturer": "Unknown",
+ "manufacturer": "Zone3D",
"file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0],
"machine_extruder_trains":
@@ -16,9 +16,7 @@
"overrides": {
"prime_tower_size": { "default_value": 10.350983390135314 },
- "material_print_temperature": { "default_value": 260 },
"layer_height": { "default_value": 0.14 },
- "speed_travel": { "default_value": 150 },
"machine_extruder_count": { "default_value": 1 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
diff --git a/resources/definitions/zyyx_agile.def.json b/resources/definitions/zyyx_agile.def.json
index 17265bf6f6..a4b3c3ee8b 100644
--- a/resources/definitions/zyyx_agile.def.json
+++ b/resources/definitions/zyyx_agile.def.json
@@ -33,7 +33,7 @@
"machine_center_is_zero": { "default_value": true },
"machine_gcode_flavor": { "default_value": "Makerbot" },
"machine_head_with_fans_polygon": { "default_value": [ [ -37, 50 ], [ 25, 50 ], [ 25, -40 ], [ -37, -40 ] ] },
- "gantry_height": { "default_value": 10 },
+ "gantry_height": { "value": "10" },
"machine_steps_per_mm_x": { "default_value": 88.888889 },
"machine_steps_per_mm_y": { "default_value": 88.888889 },
"machine_steps_per_mm_z": { "default_value": 400 },
diff --git a/resources/extruders/101Hero_extruder_0.def.json b/resources/extruders/101Hero_extruder_0.def.json
index 82c06e40d6..21c892133c 100644
--- a/resources/extruders/101Hero_extruder_0.def.json
+++ b/resources/extruders/101Hero_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "101Hero_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/3dator_extruder_0.def.json b/resources/extruders/3dator_extruder_0.def.json
index 6749eb7bb4..97b03518f7 100644
--- a/resources/extruders/3dator_extruder_0.def.json
+++ b/resources/extruders/3dator_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "3dator_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/Mark2_extruder1.def.json b/resources/extruders/Mark2_extruder1.def.json
new file mode 100644
index 0000000000..27becf88ff
--- /dev/null
+++ b/resources/extruders/Mark2_extruder1.def.json
@@ -0,0 +1,18 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "Mark2_for_Ultimaker2",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 }
+ }
+}
diff --git a/resources/extruders/Mark2_extruder2.def.json b/resources/extruders/Mark2_extruder2.def.json
new file mode 100644
index 0000000000..ac654d9c00
--- /dev/null
+++ b/resources/extruders/Mark2_extruder2.def.json
@@ -0,0 +1,18 @@
+{
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "Mark2_for_Ultimaker2",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 }
+ }
+}
diff --git a/resources/extruders/abax_pri3_extruder_0.def.json b/resources/extruders/abax_pri3_extruder_0.def.json
index 27e86d6042..618ca7f596 100644
--- a/resources/extruders/abax_pri3_extruder_0.def.json
+++ b/resources/extruders/abax_pri3_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "abax_pri3_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/abax_pri5_extruder_0.def.json b/resources/extruders/abax_pri5_extruder_0.def.json
index 842e76e5f3..4a96b5e12e 100644
--- a/resources/extruders/abax_pri5_extruder_0.def.json
+++ b/resources/extruders/abax_pri5_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "abax_pri5_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/abax_titan_extruder_0.def.json b/resources/extruders/abax_titan_extruder_0.def.json
index 79e1974def..078b9f0470 100644
--- a/resources/extruders/abax_titan_extruder_0.def.json
+++ b/resources/extruders/abax_titan_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "abax_titan_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/alfawise_u20_extruder_0.def.json b/resources/extruders/alfawise_u20_extruder_0.def.json
index 2fbe3f1772..6bb2bde534 100644
--- a/resources/extruders/alfawise_u20_extruder_0.def.json
+++ b/resources/extruders/alfawise_u20_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "alfawise_u20_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/alfawise_u30_extruder_0.def.json b/resources/extruders/alfawise_u30_extruder_0.def.json
index 37f59eb567..4014b5ab62 100644
--- a/resources/extruders/alfawise_u30_extruder_0.def.json
+++ b/resources/extruders/alfawise_u30_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "alfawise_u30_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/alya3dp_extruder_0.def.json b/resources/extruders/alya3dp_extruder_0.def.json
index 3676f01ad2..5e05210e2c 100644
--- a/resources/extruders/alya3dp_extruder_0.def.json
+++ b/resources/extruders/alya3dp_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "alya3dp_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/creality_cr10_extruder_0.def.json b/resources/extruders/anet_a6_extruder_0.def.json
similarity index 80%
rename from resources/extruders/creality_cr10_extruder_0.def.json
rename to resources/extruders/anet_a6_extruder_0.def.json
index 3a259b672b..c87160a542 100644
--- a/resources/extruders/creality_cr10_extruder_0.def.json
+++ b/resources/extruders/anet_a6_extruder_0.def.json
@@ -1,10 +1,9 @@
{
- "id": "creality_cr10_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_cr10",
+ "machine": "anet_a6",
"position": "0"
},
diff --git a/resources/extruders/anycubic_4max_extruder_0.def.json b/resources/extruders/anycubic_4max_extruder_0.def.json
index 5c2ab8d479..9ea55928b8 100644
--- a/resources/extruders/anycubic_4max_extruder_0.def.json
+++ b/resources/extruders/anycubic_4max_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "anycubic_4max_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/anycubic_chiron_extruder_0.def.json b/resources/extruders/anycubic_chiron_extruder_0.def.json
index cc48df08bb..b4117c755a 100644
--- a/resources/extruders/anycubic_chiron_extruder_0.def.json
+++ b/resources/extruders/anycubic_chiron_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "anycubic_chiron_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/anycubic_i3_mega_extruder_0.def.json b/resources/extruders/anycubic_i3_mega_extruder_0.def.json
index 6d9c330536..f15eab4829 100644
--- a/resources/extruders/anycubic_i3_mega_extruder_0.def.json
+++ b/resources/extruders/anycubic_i3_mega_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "anycubic_i3_mega_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/bfb_extruder_0.def.json b/resources/extruders/bfb_extruder_0.def.json
index 88c81ee03e..6dd995d098 100644
--- a/resources/extruders/bfb_extruder_0.def.json
+++ b/resources/extruders/bfb_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "bfb_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/bibo2_dual_extruder_0.def.json b/resources/extruders/bibo2_dual_extruder_0.def.json
index f83801fa0c..91508ecc6d 100644
--- a/resources/extruders/bibo2_dual_extruder_0.def.json
+++ b/resources/extruders/bibo2_dual_extruder_0.def.json
@@ -1,46 +1,45 @@
{
- "id": "BIBO1",
- "version": 2,
- "name": "Extruder 1",
- "inherits": "fdmextruder",
- "metadata": {
- "machine": "BIBO2 dual",
- "position": "0"
- },
- "overrides": {
- "extruder_nr": {
- "default_value": 0,
- "maximum_value": "1"
- },
- "material_diameter": {
- "default_value": 1.75
- },
- "machine_nozzle_size": {
- "default_value": 0.4
- },
- "machine_nozzle_offset_x": {
- "default_value": 0.0
- },
- "machine_nozzle_offset_y": {
- "default_value": 0.0
- },
- "machine_extruder_start_pos_abs": {
- "default_value": true
- },
- "machine_extruder_start_pos_x": {
- "value": "prime_tower_position_x"
- },
- "machine_extruder_start_pos_y": {
- "value": "prime_tower_position_y"
- },
- "machine_extruder_end_pos_abs": {
- "default_value": true
- },
- "machine_extruder_end_pos_x": {
- "value": "prime_tower_position_x"
- },
- "machine_extruder_end_pos_y": {
- "value": "prime_tower_position_y"
- }
- }
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "bibo2_dual",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": 0.0
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": 0.0
+ },
+ "machine_extruder_start_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_start_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_start_pos_y": {
+ "value": "prime_tower_position_y"
+ },
+ "machine_extruder_end_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_end_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_end_pos_y": {
+ "value": "prime_tower_position_y"
+ }
+ }
}
diff --git a/resources/extruders/bibo2_dual_extruder_1.def.json b/resources/extruders/bibo2_dual_extruder_1.def.json
index 5f479ba54b..129ad27273 100644
--- a/resources/extruders/bibo2_dual_extruder_1.def.json
+++ b/resources/extruders/bibo2_dual_extruder_1.def.json
@@ -1,46 +1,45 @@
{
- "id": "BIBO2",
- "version": 2,
- "name": "Extruder 2",
- "inherits": "fdmextruder",
- "metadata": {
- "machine": "BIBO2 dual",
- "position": "1"
- },
- "overrides": {
- "extruder_nr": {
- "default_value": 1,
- "maximum_value": "1"
- },
- "material_diameter": {
- "default_value": 1.75
- },
- "machine_nozzle_size": {
- "default_value": 0.4
- },
- "machine_nozzle_offset_x": {
- "default_value": 0.0
- },
- "machine_nozzle_offset_y": {
- "default_value": 0.0
- },
- "machine_extruder_start_pos_abs": {
- "default_value": true
- },
- "machine_extruder_start_pos_x": {
- "value": "prime_tower_position_x"
- },
- "machine_extruder_start_pos_y": {
- "value": "prime_tower_position_y"
- },
- "machine_extruder_end_pos_abs": {
- "default_value": true
- },
- "machine_extruder_end_pos_x": {
- "value": "prime_tower_position_x"
- },
- "machine_extruder_end_pos_y": {
- "value": "prime_tower_position_y"
- }
- }
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "bibo2_dual",
+ "position": "1"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": 0.0
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": 0.0
+ },
+ "machine_extruder_start_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_start_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_start_pos_y": {
+ "value": "prime_tower_position_y"
+ },
+ "machine_extruder_end_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_end_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_end_pos_y": {
+ "value": "prime_tower_position_y"
+ }
+ }
}
diff --git a/resources/extruders/bq_hephestos_2_extruder_0.def.json b/resources/extruders/bq_hephestos_2_extruder_0.def.json
index 833907937d..d58d8d755a 100644
--- a/resources/extruders/bq_hephestos_2_extruder_0.def.json
+++ b/resources/extruders/bq_hephestos_2_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "bq_hephestos_2_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/bq_hephestos_extruder_0.def.json b/resources/extruders/bq_hephestos_extruder_0.def.json
index 753778f399..dc9b42d66d 100644
--- a/resources/extruders/bq_hephestos_extruder_0.def.json
+++ b/resources/extruders/bq_hephestos_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "bq_hephestos_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/bq_hephestos_xl_extruder_0.def.json b/resources/extruders/bq_hephestos_xl_extruder_0.def.json
index 91cac04dc9..a52032f129 100644
--- a/resources/extruders/bq_hephestos_xl_extruder_0.def.json
+++ b/resources/extruders/bq_hephestos_xl_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "bq_hephestos_xl_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/bq_witbox_2_extruder_0.def.json b/resources/extruders/bq_witbox_2_extruder_0.def.json
index 04107f4471..62fe62ad0b 100644
--- a/resources/extruders/bq_witbox_2_extruder_0.def.json
+++ b/resources/extruders/bq_witbox_2_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "bq_witbox_2_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/bq_witbox_extruder_0.def.json b/resources/extruders/bq_witbox_extruder_0.def.json
index d3a5c677af..37b1492676 100644
--- a/resources/extruders/bq_witbox_extruder_0.def.json
+++ b/resources/extruders/bq_witbox_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "bq_witbox_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/builder_premium_large_front.def.json b/resources/extruders/builder_premium_large_front.def.json
index 4834bc8fd9..dc1c557304 100644
--- a/resources/extruders/builder_premium_large_front.def.json
+++ b/resources/extruders/builder_premium_large_front.def.json
@@ -1,5 +1,4 @@
{
- "id": "builder_premium_large_front",
"version": 2,
"name": "Front Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/builder_premium_large_rear.def.json b/resources/extruders/builder_premium_large_rear.def.json
index f257749ea4..5dbe6d30c9 100644
--- a/resources/extruders/builder_premium_large_rear.def.json
+++ b/resources/extruders/builder_premium_large_rear.def.json
@@ -1,5 +1,4 @@
{
- "id": "builder_premium_large_rear",
"version": 2,
"name": "Rear Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/builder_premium_medium_front.def.json b/resources/extruders/builder_premium_medium_front.def.json
index 05dcb3d49f..2d38e48aab 100644
--- a/resources/extruders/builder_premium_medium_front.def.json
+++ b/resources/extruders/builder_premium_medium_front.def.json
@@ -1,5 +1,4 @@
{
- "id": "builder_premium_medium_front",
"version": 2,
"name": "Front Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/builder_premium_medium_rear.def.json b/resources/extruders/builder_premium_medium_rear.def.json
index 3461e07f09..0a789c38f1 100644
--- a/resources/extruders/builder_premium_medium_rear.def.json
+++ b/resources/extruders/builder_premium_medium_rear.def.json
@@ -1,5 +1,4 @@
{
- "id": "builder_premium_medium_rear",
"version": 2,
"name": "Rear Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/builder_premium_small_front.def.json b/resources/extruders/builder_premium_small_front.def.json
index 7a1c352c73..b36c535aeb 100644
--- a/resources/extruders/builder_premium_small_front.def.json
+++ b/resources/extruders/builder_premium_small_front.def.json
@@ -1,5 +1,4 @@
{
- "id": "builder_premium_small_front",
"version": 2,
"name": "Front Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/builder_premium_small_rear.def.json b/resources/extruders/builder_premium_small_rear.def.json
index 7085236a5c..8e00d0cc39 100644
--- a/resources/extruders/builder_premium_small_rear.def.json
+++ b/resources/extruders/builder_premium_small_rear.def.json
@@ -1,5 +1,4 @@
{
- "id": "builder_premium_small_rear",
"version": 2,
"name": "Rear Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cartesio_extruder_0.def.json b/resources/extruders/cartesio_extruder_0.def.json
index 6d2b5f634e..ad27d4854c 100644
--- a/resources/extruders/cartesio_extruder_0.def.json
+++ b/resources/extruders/cartesio_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "cartesio_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cartesio_extruder_1.def.json b/resources/extruders/cartesio_extruder_1.def.json
index 3d49a220c0..1699a9c6a8 100644
--- a/resources/extruders/cartesio_extruder_1.def.json
+++ b/resources/extruders/cartesio_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "cartesio_extruder_1",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cartesio_extruder_2.def.json b/resources/extruders/cartesio_extruder_2.def.json
index 1f8f8b9ca9..2521ada681 100644
--- a/resources/extruders/cartesio_extruder_2.def.json
+++ b/resources/extruders/cartesio_extruder_2.def.json
@@ -1,5 +1,4 @@
{
- "id": "cartesio_extruder_2",
"version": 2,
"name": "Extruder 3",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cartesio_extruder_3.def.json b/resources/extruders/cartesio_extruder_3.def.json
index 0b1cfe493e..c844e7ce54 100644
--- a/resources/extruders/cartesio_extruder_3.def.json
+++ b/resources/extruders/cartesio_extruder_3.def.json
@@ -1,5 +1,4 @@
{
- "id": "cartesio_extruder_3",
"version": 2,
"name": "Extruder 4",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json b/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json
index 26d847483d..dfa06c776a 100644
--- a/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json
+++ b/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "cocoon_create_modelmaker_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cr-x_extruder_0.def.json b/resources/extruders/cr-x_extruder_0.def.json
index 8135815afb..d9b7b03021 100644
--- a/resources/extruders/cr-x_extruder_0.def.json
+++ b/resources/extruders/cr-x_extruder_0.def.json
@@ -1,10 +1,9 @@
{
- "id": "cr-x_extruder_0",
"version": 2,
"name": "Left Extruder",
"inherits": "fdmextruder",
"metadata": {
- "machine": "Creality CR-X",
+ "machine": "creality_cr-x",
"position": "0"
},
diff --git a/resources/extruders/cr-x_extruder_1.def.json b/resources/extruders/cr-x_extruder_1.def.json
index 9313f2ea78..8e763df64f 100644
--- a/resources/extruders/cr-x_extruder_1.def.json
+++ b/resources/extruders/cr-x_extruder_1.def.json
@@ -1,10 +1,9 @@
{
- "id": "cr-x_extruder_1",
"version": 2,
"name": "Right Extruder",
"inherits": "fdmextruder",
"metadata": {
- "machine": "Creality CR-X",
+ "machine": "creality_cr-x",
"position": "1"
},
diff --git a/resources/extruders/creality_cr10s4_extruder_0.def.json b/resources/extruders/creality_base_extruder_0.def.json
similarity index 80%
rename from resources/extruders/creality_cr10s4_extruder_0.def.json
rename to resources/extruders/creality_base_extruder_0.def.json
index 8a40c6431f..a173d1c2fa 100644
--- a/resources/extruders/creality_cr10s4_extruder_0.def.json
+++ b/resources/extruders/creality_base_extruder_0.def.json
@@ -1,10 +1,9 @@
{
- "id": "creality_cr10s4_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_cr10s4",
+ "machine": "creality_base",
"position": "0"
},
@@ -12,5 +11,6 @@
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }
+
}
}
diff --git a/resources/extruders/creatable_d3_extruder_0.def.json b/resources/extruders/creatable_d3_extruder_0.def.json
index 7d45bb8e8a..95883d0f69 100644
--- a/resources/extruders/creatable_d3_extruder_0.def.json
+++ b/resources/extruders/creatable_d3_extruder_0.def.json
@@ -1,10 +1,9 @@
{
- "id": "creatable_d3_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "Creatable_D3",
+ "machine": "creatable_d3",
"position": "0"
},
diff --git a/resources/extruders/cubicon_3dp_110f_extruder_0.def.json b/resources/extruders/cubicon_3dp_110f_extruder_0.def.json
index 9c854fd2a1..048c12b992 100644
--- a/resources/extruders/cubicon_3dp_110f_extruder_0.def.json
+++ b/resources/extruders/cubicon_3dp_110f_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "cubicon_3dp_110f_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cubicon_3dp_210f_extruder_0.def.json b/resources/extruders/cubicon_3dp_210f_extruder_0.def.json
index 8a8573760a..07fe7f3769 100644
--- a/resources/extruders/cubicon_3dp_210f_extruder_0.def.json
+++ b/resources/extruders/cubicon_3dp_210f_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "cubicon_3dp_210f_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cubicon_3dp_310f_extruder_0.def.json b/resources/extruders/cubicon_3dp_310f_extruder_0.def.json
index 4edbbd5a6c..8dc336877f 100644
--- a/resources/extruders/cubicon_3dp_310f_extruder_0.def.json
+++ b/resources/extruders/cubicon_3dp_310f_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "cubicon_3dp_310f_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/cubicon_dual_pro_a30_extruder_0.def.json b/resources/extruders/cubicon_dual_pro_a30_extruder_0.def.json
new file mode 100644
index 0000000000..6c8993e799
--- /dev/null
+++ b/resources/extruders/cubicon_dual_pro_a30_extruder_0.def.json
@@ -0,0 +1,26 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cubicon_dual_pro_a30",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": -27.3
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": -19.9
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
diff --git a/resources/extruders/cubicon_dual_pro_a30_extruder_1.def.json b/resources/extruders/cubicon_dual_pro_a30_extruder_1.def.json
new file mode 100644
index 0000000000..ccdfdee1f7
--- /dev/null
+++ b/resources/extruders/cubicon_dual_pro_a30_extruder_1.def.json
@@ -0,0 +1,26 @@
+{
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cubicon_dual_pro_a30",
+ "position": "1"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": -27.3
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": -19.9
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
diff --git a/resources/extruders/cubicon_style_plus_a15_extruder_0.def.json b/resources/extruders/cubicon_style_plus_a15_extruder_0.def.json
new file mode 100644
index 0000000000..12d022cd1e
--- /dev/null
+++ b/resources/extruders/cubicon_style_plus_a15_extruder_0.def.json
@@ -0,0 +1,26 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cubicon_style_plus_a15",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": -4.00
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": -7.00
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
diff --git a/resources/extruders/custom_extruder_1.def.json b/resources/extruders/custom_extruder_1.def.json
index 859c6a2f22..942f3e96b9 100644
--- a/resources/extruders/custom_extruder_1.def.json
+++ b/resources/extruders/custom_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_1",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_2.def.json b/resources/extruders/custom_extruder_2.def.json
index eecda5dfcd..cd43efa994 100644
--- a/resources/extruders/custom_extruder_2.def.json
+++ b/resources/extruders/custom_extruder_2.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_2",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_3.def.json b/resources/extruders/custom_extruder_3.def.json
index 77909ec05d..be5bdd0e6a 100644
--- a/resources/extruders/custom_extruder_3.def.json
+++ b/resources/extruders/custom_extruder_3.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_3",
"version": 2,
"name": "Extruder 3",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_4.def.json b/resources/extruders/custom_extruder_4.def.json
index be792c3a8e..ce1df0a5f5 100644
--- a/resources/extruders/custom_extruder_4.def.json
+++ b/resources/extruders/custom_extruder_4.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_4",
"version": 2,
"name": "Extruder 4",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_5.def.json b/resources/extruders/custom_extruder_5.def.json
index ea64605041..beb4786505 100644
--- a/resources/extruders/custom_extruder_5.def.json
+++ b/resources/extruders/custom_extruder_5.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_5",
"version": 2,
"name": "Extruder 5",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_6.def.json b/resources/extruders/custom_extruder_6.def.json
index fd27fadace..7f1e1a1343 100644
--- a/resources/extruders/custom_extruder_6.def.json
+++ b/resources/extruders/custom_extruder_6.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_6",
"version": 2,
"name": "Extruder 6",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_7.def.json b/resources/extruders/custom_extruder_7.def.json
index cf003d1a6b..e4239f35f0 100644
--- a/resources/extruders/custom_extruder_7.def.json
+++ b/resources/extruders/custom_extruder_7.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_7",
"version": 2,
"name": "Extruder 7",
"inherits": "fdmextruder",
diff --git a/resources/extruders/custom_extruder_8.def.json b/resources/extruders/custom_extruder_8.def.json
index f418a55186..7671825792 100644
--- a/resources/extruders/custom_extruder_8.def.json
+++ b/resources/extruders/custom_extruder_8.def.json
@@ -1,5 +1,4 @@
{
- "id": "custom_extruder_8",
"version": 2,
"name": "Extruder 8",
"inherits": "fdmextruder",
diff --git a/resources/extruders/delta_go_extruder_0.def.json b/resources/extruders/delta_go_extruder_0.def.json
index 2262270dfb..330cde08bf 100644
--- a/resources/extruders/delta_go_extruder_0.def.json
+++ b/resources/extruders/delta_go_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "delta_go_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/deltabot_extruder_0.def.json b/resources/extruders/deltabot_extruder_0.def.json
index e13d6a6ee3..d4773ccf9f 100644
--- a/resources/extruders/deltabot_extruder_0.def.json
+++ b/resources/extruders/deltabot_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "deltabot_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/deltacomb_extruder_0.def.json b/resources/extruders/deltacomb_extruder_0.def.json
index 64c512b7fe..875655d5c7 100755
--- a/resources/extruders/deltacomb_extruder_0.def.json
+++ b/resources/extruders/deltacomb_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "deltacomb_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/deltacomb_extruder_1.def.json b/resources/extruders/deltacomb_extruder_1.def.json
index 1657688482..b1f30f4624 100755
--- a/resources/extruders/deltacomb_extruder_1.def.json
+++ b/resources/extruders/deltacomb_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "deltacomb_extruder_1",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/easyarts_ares_extruder_0.def.json b/resources/extruders/easyarts_ares_extruder_0.def.json
index ec7ba81c57..4ddd476dbb 100644
--- a/resources/extruders/easyarts_ares_extruder_0.def.json
+++ b/resources/extruders/easyarts_ares_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "easyarts_ares_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/creality_cr10s5_extruder_0.def.json b/resources/extruders/erzay3d_extruder_0.def.json
similarity index 80%
rename from resources/extruders/creality_cr10s5_extruder_0.def.json
rename to resources/extruders/erzay3d_extruder_0.def.json
index 98b701ae2e..a9cea62897 100644
--- a/resources/extruders/creality_cr10s5_extruder_0.def.json
+++ b/resources/extruders/erzay3d_extruder_0.def.json
@@ -1,10 +1,9 @@
{
- "id": "creality_cr10s5_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_cr10s5",
+ "machine": "erzay3d",
"position": "0"
},
diff --git a/resources/extruders/fabtotum_extruder_0.def.json b/resources/extruders/fabtotum_extruder_0.def.json
index 5ed4da6256..a763fbcc15 100644
--- a/resources/extruders/fabtotum_extruder_0.def.json
+++ b/resources/extruders/fabtotum_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "fabtotum_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/felixpro2_dual_extruder_0.def.json b/resources/extruders/felixpro2_dual_extruder_0.def.json
new file mode 100644
index 0000000000..4278a532f9
--- /dev/null
+++ b/resources/extruders/felixpro2_dual_extruder_0.def.json
@@ -0,0 +1,27 @@
+{
+ "version": 2,
+ "name": "Left Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "felixpro2dual",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.35 },
+ "material_diameter": { "default_value": 1.75 },
+
+ "machine_extruder_start_pos_abs": { "default_value": true },
+ "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" },
+ "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" },
+ "machine_extruder_end_pos_abs": { "default_value": true },
+ "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" },
+ "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }
+ }
+}
diff --git a/resources/extruders/felixpro2_dual_extruder_1.def.json b/resources/extruders/felixpro2_dual_extruder_1.def.json
new file mode 100644
index 0000000000..195aad474d
--- /dev/null
+++ b/resources/extruders/felixpro2_dual_extruder_1.def.json
@@ -0,0 +1,27 @@
+{
+ "version": 2,
+ "name": "Right Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "felixpro2dual",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "2"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.35 },
+ "material_diameter": { "default_value": 1.75 },
+
+ "machine_extruder_start_pos_abs": { "default_value": true },
+ "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" },
+ "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" },
+ "machine_extruder_end_pos_abs": { "default_value": true },
+ "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" },
+ "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }
+ }
+}
diff --git a/resources/extruders/felixtec4_dual_extruder_0.def.json b/resources/extruders/felixtec4_dual_extruder_0.def.json
index 2a2d0468e1..1821b0e601 100644
--- a/resources/extruders/felixtec4_dual_extruder_0.def.json
+++ b/resources/extruders/felixtec4_dual_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "felixtec4_dual_extruder_0",
"version": 2,
"name": "Left Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/felixtec4_dual_extruder_1.def.json b/resources/extruders/felixtec4_dual_extruder_1.def.json
index 5d7e9c74a3..37a99c5fb4 100644
--- a/resources/extruders/felixtec4_dual_extruder_1.def.json
+++ b/resources/extruders/felixtec4_dual_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "felixtec4_dual_extruder_1",
"version": 2,
"name": "Right Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/flsun_qq_extruder.def.json b/resources/extruders/flsun_qq_extruder.def.json
index 7c93776836..c7ca0ed6eb 100644
--- a/resources/extruders/flsun_qq_extruder.def.json
+++ b/resources/extruders/flsun_qq_extruder.def.json
@@ -1,5 +1,4 @@
{
- "id": "flsun_qq_extruder",
"version": 2,
"name": "Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/creality_ender3_extruder_0.def.json b/resources/extruders/flsun_qq_s_extruder_0.def.json
similarity index 80%
rename from resources/extruders/creality_ender3_extruder_0.def.json
rename to resources/extruders/flsun_qq_s_extruder_0.def.json
index 431366c777..e61056fcd3 100644
--- a/resources/extruders/creality_ender3_extruder_0.def.json
+++ b/resources/extruders/flsun_qq_s_extruder_0.def.json
@@ -1,10 +1,9 @@
{
- "id": "creality_ender3_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_ender3",
+ "machine": "flsun_qq_s",
"position": "0"
},
diff --git a/resources/extruders/folgertech_FT-5_extruder_0.def.json b/resources/extruders/folgertech_FT-5_extruder_0.def.json
index 8ba9d130c6..861b0e7a7e 100644
--- a/resources/extruders/folgertech_FT-5_extruder_0.def.json
+++ b/resources/extruders/folgertech_FT-5_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "folgertech_FT-5_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/geeetech_a30_extruder_0.def.json b/resources/extruders/geeetech_a30_extruder_0.def.json
new file mode 100644
index 0000000000..90cb496877
--- /dev/null
+++ b/resources/extruders/geeetech_a30_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "geeetech_a30",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/gmax15plus_dual_extruder_0.def.json b/resources/extruders/gmax15plus_dual_extruder_0.def.json
index d3146a0576..45f35dee1f 100644
--- a/resources/extruders/gmax15plus_dual_extruder_0.def.json
+++ b/resources/extruders/gmax15plus_dual_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "gmax15plus_dual_extruder_0",
"version": 2,
"name": "Left Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/gmax15plus_dual_extruder_1.def.json b/resources/extruders/gmax15plus_dual_extruder_1.def.json
index 7b7354d794..6d0d5db06f 100644
--- a/resources/extruders/gmax15plus_dual_extruder_1.def.json
+++ b/resources/extruders/gmax15plus_dual_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "gmax15plus_dual_extruder_1",
"version": 2,
"name": "Right Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/gmax15plus_extruder_0.def.json b/resources/extruders/gmax15plus_extruder_0.def.json
index 70389745b3..5b0889d46d 100644
--- a/resources/extruders/gmax15plus_extruder_0.def.json
+++ b/resources/extruders/gmax15plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "gmax15plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/grr_neo_extruder_0.def.json b/resources/extruders/grr_neo_extruder_0.def.json
index 6d76c90796..a9f1fa4faa 100644
--- a/resources/extruders/grr_neo_extruder_0.def.json
+++ b/resources/extruders/grr_neo_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "grr_neo_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/hBp_extruder_left.def.json b/resources/extruders/hBp_extruder_left.def.json
index 7e71ca27a8..ce23f27c29 100644
--- a/resources/extruders/hBp_extruder_left.def.json
+++ b/resources/extruders/hBp_extruder_left.def.json
@@ -1,5 +1,4 @@
{
- "id": "hBp_extruder_left",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/hBp_extruder_right.def.json b/resources/extruders/hBp_extruder_right.def.json
index acd2312268..170556a1fd 100644
--- a/resources/extruders/hBp_extruder_right.def.json
+++ b/resources/extruders/hBp_extruder_right.def.json
@@ -1,5 +1,4 @@
{
- "id": "hBp_extruder_right",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/hellbot_adonis_extruder.def.json b/resources/extruders/hellbot_adonis_extruder.def.json
new file mode 100644
index 0000000000..4201f6b393
--- /dev/null
+++ b/resources/extruders/hellbot_adonis_extruder.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hellbot_adonis",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/hellbot_magna_dual_extruder_1.def.json b/resources/extruders/hellbot_magna_dual_extruder_1.def.json
new file mode 100644
index 0000000000..a31a3fdd70
--- /dev/null
+++ b/resources/extruders/hellbot_magna_dual_extruder_1.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hellbot_magna_dual",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/hellbot_magna_dual_extruder_2.def.json b/resources/extruders/hellbot_magna_dual_extruder_2.def.json
new file mode 100644
index 0000000000..651c39d53b
--- /dev/null
+++ b/resources/extruders/hellbot_magna_dual_extruder_2.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hellbot_magna_dual",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 1 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/hellbot_magna_i_extruder.def.json b/resources/extruders/hellbot_magna_i_extruder.def.json
new file mode 100644
index 0000000000..70117c2aed
--- /dev/null
+++ b/resources/extruders/hellbot_magna_i_extruder.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hellbot_magna_I",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/hms434_tool_1.def.json b/resources/extruders/hms434_tool_1.def.json
new file mode 100644
index 0000000000..3a1619d98b
--- /dev/null
+++ b/resources/extruders/hms434_tool_1.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool1\nM109 T0 S{material_print_temperature}\nG1 X-18 Y-50 F9000\nG1 X150 Y10 F9000\n\n"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\nG1 X150 Y10 F9000\nG1 X-20 Y-50 F9000\nG1 Y-100 F3000\n; ending tool1\n\n"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_2.def.json b/resources/extruders/hms434_tool_2.def.json
new file mode 100644
index 0000000000..3a174f82b9
--- /dev/null
+++ b/resources/extruders/hms434_tool_2.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool2\nM109 T1 S{material_print_temperature}\nG1 X-18 Y-50 F9000\nG1 X150 Y10 F9000\n\n"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\nG1 X150 Y10 F9000\nG1 X-20 Y-50 F9000\nG1 Y-100 F3000\n; ending tool2\n\n"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_3.def.json b/resources/extruders/hms434_tool_3.def.json
new file mode 100644
index 0000000000..e1e237d332
--- /dev/null
+++ b/resources/extruders/hms434_tool_3.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 3",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "2"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 2,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool3"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\n;ending tool3"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_4.def.json b/resources/extruders/hms434_tool_4.def.json
new file mode 100644
index 0000000000..1a68d5aff5
--- /dev/null
+++ b/resources/extruders/hms434_tool_4.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 4",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "3"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 3,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool4"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\n;ending tool4"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_5.def.json b/resources/extruders/hms434_tool_5.def.json
new file mode 100644
index 0000000000..b56e8be84e
--- /dev/null
+++ b/resources/extruders/hms434_tool_5.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 5",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "4"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 4,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool5"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\n;ending tool5"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_6.def.json b/resources/extruders/hms434_tool_6.def.json
new file mode 100644
index 0000000000..b8c8cdf062
--- /dev/null
+++ b/resources/extruders/hms434_tool_6.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 6",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "5"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 5,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool6"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\n;ending tool6"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_7.def.json b/resources/extruders/hms434_tool_7.def.json
new file mode 100644
index 0000000000..3fc04078fa
--- /dev/null
+++ b/resources/extruders/hms434_tool_7.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 7",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "6"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 6,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool7"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\n;ending tool7"
+ }
+ }
+}
diff --git a/resources/extruders/hms434_tool_8.def.json b/resources/extruders/hms434_tool_8.def.json
new file mode 100644
index 0000000000..faa6f36871
--- /dev/null
+++ b/resources/extruders/hms434_tool_8.def.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "name": "Tool 8",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "hms434",
+ "position": "7"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 7,
+ "maximum_value": "8"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_extruder_start_code": {
+ "default_value": "\n;changing to tool8"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\n;ending tool8"
+ }
+ }
+}
diff --git a/resources/extruders/imade3d_jellybox_2_extruder_0.def.json b/resources/extruders/imade3d_jellybox_2_extruder_0.def.json
new file mode 100644
index 0000000000..ca25b62286
--- /dev/null
+++ b/resources/extruders/imade3d_jellybox_2_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "imade3d_jellybox_2",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/imade3d_jellybox_extruder_0.def.json b/resources/extruders/imade3d_jellybox_extruder_0.def.json
index feaa717ee6..69c6d87d79 100644
--- a/resources/extruders/imade3d_jellybox_extruder_0.def.json
+++ b/resources/extruders/imade3d_jellybox_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "imade3d_jellybox_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/innovo_inventor_extruder_0.def.json b/resources/extruders/innovo_inventor_extruder_0.def.json
index ed599463f2..8758f3d516 100644
--- a/resources/extruders/innovo_inventor_extruder_0.def.json
+++ b/resources/extruders/innovo_inventor_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "innovo_inventor_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/jgaurora_a1_extruder_0.def.json b/resources/extruders/jgaurora_a1_extruder_0.def.json
index 71742b734a..f67d8d553e 100644
--- a/resources/extruders/jgaurora_a1_extruder_0.def.json
+++ b/resources/extruders/jgaurora_a1_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "jgaurora_a1_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/jgaurora_a3s_extruder_0.def.json b/resources/extruders/jgaurora_a3s_extruder_0.def.json
new file mode 100644
index 0000000000..9a42d0da04
--- /dev/null
+++ b/resources/extruders/jgaurora_a3s_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "jgaurora_a3s",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/jgaurora_a5_extruder_0.def.json b/resources/extruders/jgaurora_a5_extruder_0.def.json
index fbc6ba77e6..5308c57934 100644
--- a/resources/extruders/jgaurora_a5_extruder_0.def.json
+++ b/resources/extruders/jgaurora_a5_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "jgaurora_a5_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/jgaurora_jgmaker_magic_extruder_0.def.json b/resources/extruders/jgaurora_jgmaker_magic_extruder_0.def.json
new file mode 100644
index 0000000000..58beaa4cc8
--- /dev/null
+++ b/resources/extruders/jgaurora_jgmaker_magic_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "jgaurora_jgmaker_magic",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/jgaurora_z_603s_extruder_0.def.json b/resources/extruders/jgaurora_z_603s_extruder_0.def.json
index 987425b28a..647016d5ff 100644
--- a/resources/extruders/jgaurora_z_603s_extruder_0.def.json
+++ b/resources/extruders/jgaurora_z_603s_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "jgaurora_z_603s_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/julia_extruder_0.def.json b/resources/extruders/julia_extruder_0.def.json
index 53a569ccd8..ef0ca83ac4 100644
--- a/resources/extruders/julia_extruder_0.def.json
+++ b/resources/extruders/julia_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "julia_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/kemiq_q2_beta_extruder_0.def.json b/resources/extruders/kemiq_q2_beta_extruder_0.def.json
index 0c7d1b7b50..79d55223f3 100644
--- a/resources/extruders/kemiq_q2_beta_extruder_0.def.json
+++ b/resources/extruders/kemiq_q2_beta_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "kemiq_q2_beta_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/kemiq_q2_gama_extruder_0.def.json b/resources/extruders/kemiq_q2_gama_extruder_0.def.json
index bb165ca35e..ad6e6372ee 100644
--- a/resources/extruders/kemiq_q2_gama_extruder_0.def.json
+++ b/resources/extruders/kemiq_q2_gama_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "kemiq_q2_gama_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/key3d_tyro_extruder_0.def.json b/resources/extruders/key3d_tyro_extruder_0.def.json
new file mode 100644
index 0000000000..f08ae351ab
--- /dev/null
+++ b/resources/extruders/key3d_tyro_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "0.4mm Nozzle",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "key3d_tyro",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/kossel_mini_extruder_0.def.json b/resources/extruders/kossel_mini_extruder_0.def.json
index f57154e1a3..7da2cff3b1 100644
--- a/resources/extruders/kossel_mini_extruder_0.def.json
+++ b/resources/extruders/kossel_mini_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "kossel_mini_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/kossel_pro_extruder_0.def.json b/resources/extruders/kossel_pro_extruder_0.def.json
index 921e1d8bb4..48c1180f84 100644
--- a/resources/extruders/kossel_pro_extruder_0.def.json
+++ b/resources/extruders/kossel_pro_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "kossel_pro_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/kupido_extruder_0.def.json b/resources/extruders/kupido_extruder_0.def.json
index ef988d4fde..784e453bd1 100644
--- a/resources/extruders/kupido_extruder_0.def.json
+++ b/resources/extruders/kupido_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "kupido_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/leapfrog_bolt_pro_extruder_left.def.json b/resources/extruders/leapfrog_bolt_pro_extruder_left.def.json
new file mode 100644
index 0000000000..4ec859a60c
--- /dev/null
+++ b/resources/extruders/leapfrog_bolt_pro_extruder_left.def.json
@@ -0,0 +1,21 @@
+{
+ "version": 2,
+ "name": "Left extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "leapfrog_bolt_pro",
+ "position": "1"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_head_distance": { "default_value": 22 },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "machine_extruder_start_code": { "default_value": "G1 Y-32 F12000\nG1 X6 F1000\nG1 X-32 F4000\nG1 X6" }
+ }
+}
diff --git a/resources/extruders/leapfrog_bolt_pro_extruder_right.def.json b/resources/extruders/leapfrog_bolt_pro_extruder_right.def.json
new file mode 100644
index 0000000000..fe27106afd
--- /dev/null
+++ b/resources/extruders/leapfrog_bolt_pro_extruder_right.def.json
@@ -0,0 +1,21 @@
+{
+ "version": 2,
+ "name": "Right extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "leapfrog_bolt_pro",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_head_distance": { "default_value": 22 },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "machine_extruder_start_code": { "default_value": "G1 Y-32 F12000\nG1 X296 F1000\nG1 X334 F4000\nG1 X296"}
+ }
+}
diff --git a/resources/extruders/makeR_pegasus_extruder_0.def.json b/resources/extruders/makeR_pegasus_extruder_0.def.json
index e37891abde..c17c51d599 100644
--- a/resources/extruders/makeR_pegasus_extruder_0.def.json
+++ b/resources/extruders/makeR_pegasus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "makeR_pegasus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/makeR_prusa_tairona_i3_extruder_0.def.json b/resources/extruders/makeR_prusa_tairona_i3_extruder_0.def.json
index a80d4079cb..278981f355 100644
--- a/resources/extruders/makeR_prusa_tairona_i3_extruder_0.def.json
+++ b/resources/extruders/makeR_prusa_tairona_i3_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "makeR_prusa_tairona_i3_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/makeblock_mcreate_extruder_0.def.json b/resources/extruders/makeblock_mcreate_extruder_0.def.json
new file mode 100644
index 0000000000..060ea634f8
--- /dev/null
+++ b/resources/extruders/makeblock_mcreate_extruder_0.def.json
@@ -0,0 +1,20 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "makeblock_mcreate",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
diff --git a/resources/extruders/makeit_dual_1st.def.json b/resources/extruders/makeit_dual_1st.def.json
index 0f5a716e16..16374b40d1 100644
--- a/resources/extruders/makeit_dual_1st.def.json
+++ b/resources/extruders/makeit_dual_1st.def.json
@@ -1,5 +1,4 @@
{
- "id": "makeit_dual_1st",
"version": 2,
"name": "1st Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/makeit_dual_2nd.def.json b/resources/extruders/makeit_dual_2nd.def.json
index f93d670c85..562cfcbc40 100644
--- a/resources/extruders/makeit_dual_2nd.def.json
+++ b/resources/extruders/makeit_dual_2nd.def.json
@@ -1,5 +1,4 @@
{
- "id": "makeit_dual_2nd",
"version": 2,
"name": "2nd Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/makeit_l_dual_1st.def.json b/resources/extruders/makeit_l_dual_1st.def.json
index 6a9e8e3fc1..8fbc2944b1 100644
--- a/resources/extruders/makeit_l_dual_1st.def.json
+++ b/resources/extruders/makeit_l_dual_1st.def.json
@@ -1,5 +1,4 @@
{
- "id": "makeit_l_dual_1st",
"version": 2,
"name": "1st Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/makeit_l_dual_2nd.def.json b/resources/extruders/makeit_l_dual_2nd.def.json
index 72b86b22e4..e163e9565a 100644
--- a/resources/extruders/makeit_l_dual_2nd.def.json
+++ b/resources/extruders/makeit_l_dual_2nd.def.json
@@ -1,5 +1,4 @@
{
- "id": "makeit_l_dual_2nd",
"version": 2,
"name": "2nd Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/maker_starter_extruder_0.def.json b/resources/extruders/maker_starter_extruder_0.def.json
index ee94250248..76e2f74a4c 100644
--- a/resources/extruders/maker_starter_extruder_0.def.json
+++ b/resources/extruders/maker_starter_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "maker_starter_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/makerbotreplicator_extruder_0.def.json b/resources/extruders/makerbotreplicator_extruder_0.def.json
index 36a975ace1..595134d788 100644
--- a/resources/extruders/makerbotreplicator_extruder_0.def.json
+++ b/resources/extruders/makerbotreplicator_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "makerbotreplicator_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/malyan_m180_extruder_0.def.json b/resources/extruders/malyan_m180_extruder_0.def.json
index bdf5350b26..04bc70ce55 100644
--- a/resources/extruders/malyan_m180_extruder_0.def.json
+++ b/resources/extruders/malyan_m180_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "malyan_m180_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/malyan_m200_extruder_0.def.json b/resources/extruders/malyan_m200_extruder_0.def.json
index 4a135aa72d..88d99fb426 100644
--- a/resources/extruders/malyan_m200_extruder_0.def.json
+++ b/resources/extruders/malyan_m200_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "malyan_m200_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/mankati_fullscale_xt_plus_extruder_0.def.json b/resources/extruders/mankati_fullscale_xt_plus_extruder_0.def.json
index 032a577022..4cb893336e 100644
--- a/resources/extruders/mankati_fullscale_xt_plus_extruder_0.def.json
+++ b/resources/extruders/mankati_fullscale_xt_plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "mankati_fullscale_xt_plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/mendel90_extruder_0.def.json b/resources/extruders/mendel90_extruder_0.def.json
index 3ee2fd2b10..2ea4d9a7de 100644
--- a/resources/extruders/mendel90_extruder_0.def.json
+++ b/resources/extruders/mendel90_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "mendel90_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/monoprice_select_mini_v1_extruder_0.def.json b/resources/extruders/monoprice_select_mini_v1_extruder_0.def.json
index e4a899d7af..023bd6b27c 100644
--- a/resources/extruders/monoprice_select_mini_v1_extruder_0.def.json
+++ b/resources/extruders/monoprice_select_mini_v1_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "monoprice_select_mini_v1_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/monoprice_select_mini_v2_extruder_0.def.json b/resources/extruders/monoprice_select_mini_v2_extruder_0.def.json
index b727cfce1f..79ba110701 100644
--- a/resources/extruders/monoprice_select_mini_v2_extruder_0.def.json
+++ b/resources/extruders/monoprice_select_mini_v2_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "monoprice_select_mini_v2_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/nwa3d_a31_extruder_0.def.json b/resources/extruders/nwa3d_a31_extruder_0.def.json
new file mode 100644
index 0000000000..de1938956a
--- /dev/null
+++ b/resources/extruders/nwa3d_a31_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Standard 0.4mm",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "nwa3d_a31",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/nwa3d_a5_extruder_0.def.json b/resources/extruders/nwa3d_a5_extruder_0.def.json
index 5c3cc6a127..9131480732 100644
--- a/resources/extruders/nwa3d_a5_extruder_0.def.json
+++ b/resources/extruders/nwa3d_a5_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "nwa3d_a5_extruder_0",
"version": 2,
"name": "Regular 0.4mm Nozzle",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ord_extruder_0.def.json b/resources/extruders/ord_extruder_0.def.json
index 317ad70a3c..61317c4a17 100644
--- a/resources/extruders/ord_extruder_0.def.json
+++ b/resources/extruders/ord_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ord_extruder_0",
"version": 2,
"name": "0",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ord_extruder_1.def.json b/resources/extruders/ord_extruder_1.def.json
index 6e29ad2f2b..43bc11fa71 100644
--- a/resources/extruders/ord_extruder_1.def.json
+++ b/resources/extruders/ord_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "ord_extruder_1",
"version": 2,
"name": "1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ord_extruder_2.def.json b/resources/extruders/ord_extruder_2.def.json
index 849930c988..84bcbd5332 100644
--- a/resources/extruders/ord_extruder_2.def.json
+++ b/resources/extruders/ord_extruder_2.def.json
@@ -1,5 +1,4 @@
{
- "id": "ord_extruder_2",
"version": 2,
"name": "2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ord_extruder_3.def.json b/resources/extruders/ord_extruder_3.def.json
index eb3676c14f..db81f82b78 100644
--- a/resources/extruders/ord_extruder_3.def.json
+++ b/resources/extruders/ord_extruder_3.def.json
@@ -1,5 +1,4 @@
{
- "id": "ord_extruder_3",
"version": 2,
"name": "3",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ord_extruder_4.def.json b/resources/extruders/ord_extruder_4.def.json
index 291e9e5501..2ca7609e06 100644
--- a/resources/extruders/ord_extruder_4.def.json
+++ b/resources/extruders/ord_extruder_4.def.json
@@ -1,5 +1,4 @@
{
- "id": "ord_extruder_4",
"version": 2,
"name": "4",
"inherits": "fdmextruder",
diff --git a/resources/extruders/peopoly_moai_extruder_0.def.json b/resources/extruders/peopoly_moai_extruder_0.def.json
index bbffd4ac4d..1acf5b499f 100644
--- a/resources/extruders/peopoly_moai_extruder_0.def.json
+++ b/resources/extruders/peopoly_moai_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "peopoly_moai_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/printrbot_play_extruder_0.def.json b/resources/extruders/printrbot_play_extruder_0.def.json
index ef1284758b..682810c8d8 100644
--- a/resources/extruders/printrbot_play_extruder_0.def.json
+++ b/resources/extruders/printrbot_play_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "printrbot_play_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/printrbot_play_heated_extruder_0.def.json b/resources/extruders/printrbot_play_heated_extruder_0.def.json
index 0a3eeb3d06..72335e82d6 100644
--- a/resources/extruders/printrbot_play_heated_extruder_0.def.json
+++ b/resources/extruders/printrbot_play_heated_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "printrbot_play_heated_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/printrbot_simple_extended_extruder_0.def.json b/resources/extruders/printrbot_simple_extended_extruder_0.def.json
index 71c8863552..b50a142d2e 100644
--- a/resources/extruders/printrbot_simple_extended_extruder_0.def.json
+++ b/resources/extruders/printrbot_simple_extended_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "printrbot_simple_extended_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/printrbot_simple_extruder_0.def.json b/resources/extruders/printrbot_simple_extruder_0.def.json
index e97977e07e..4fa5d7fbf2 100644
--- a/resources/extruders/printrbot_simple_extruder_0.def.json
+++ b/resources/extruders/printrbot_simple_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "printrbot_simple_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/printrbot_simple_makers_kit_extruder_0.def.json b/resources/extruders/printrbot_simple_makers_kit_extruder_0.def.json
index f002bb9cf5..a58195fdfb 100644
--- a/resources/extruders/printrbot_simple_makers_kit_extruder_0.def.json
+++ b/resources/extruders/printrbot_simple_makers_kit_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "printrbot_simple_makers_kit_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/prusa_i3_extruder_0.def.json b/resources/extruders/prusa_i3_extruder_0.def.json
index 11c52e062b..dbb01032b8 100644
--- a/resources/extruders/prusa_i3_extruder_0.def.json
+++ b/resources/extruders/prusa_i3_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "prusa_i3_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/prusa_i3_mk2_extruder_0.def.json b/resources/extruders/prusa_i3_mk2_extruder_0.def.json
index a56aae4300..e802687062 100644
--- a/resources/extruders/prusa_i3_mk2_extruder_0.def.json
+++ b/resources/extruders/prusa_i3_mk2_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "prusa_i3_mk2_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/prusa_i3_mk3_extruder_0.def.json b/resources/extruders/prusa_i3_mk3_extruder_0.def.json
new file mode 100644
index 0000000000..29156f0d70
--- /dev/null
+++ b/resources/extruders/prusa_i3_mk3_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "prusa_i3_mk3",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/prusa_i3_xl_extruder_0.def.json b/resources/extruders/prusa_i3_xl_extruder_0.def.json
index 5dc2ab3bc0..c4125b36ee 100644
--- a/resources/extruders/prusa_i3_xl_extruder_0.def.json
+++ b/resources/extruders/prusa_i3_xl_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "prusa_i3_xl_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/punchtec_connect_xl_extruder_0.def.json b/resources/extruders/punchtec_connect_xl_extruder_0.def.json
index 68c3d8c906..f286140167 100644
--- a/resources/extruders/punchtec_connect_xl_extruder_0.def.json
+++ b/resources/extruders/punchtec_connect_xl_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "punchtec_connect_xl_extruder_0",
"version": 2,
"name": "0",
"inherits": "fdmextruder",
diff --git a/resources/extruders/punchtec_connect_xl_extruder_1.def.json b/resources/extruders/punchtec_connect_xl_extruder_1.def.json
index a2e4b31714..47d28882cf 100644
--- a/resources/extruders/punchtec_connect_xl_extruder_1.def.json
+++ b/resources/extruders/punchtec_connect_xl_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "punchtec_connect_xl_extruder_1",
"version": 2,
"name": "1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/raise3D_N2_dual_extruder_0.def.json b/resources/extruders/raise3D_N2_dual_extruder_0.def.json
index 48746969d3..9294a73933 100644
--- a/resources/extruders/raise3D_N2_dual_extruder_0.def.json
+++ b/resources/extruders/raise3D_N2_dual_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "raise3D_N2_dual_extruder_0",
"version": 2,
"name": "Left Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/raise3D_N2_dual_extruder_1.def.json b/resources/extruders/raise3D_N2_dual_extruder_1.def.json
index 8ea6f95b16..e09cb6b9fc 100644
--- a/resources/extruders/raise3D_N2_dual_extruder_1.def.json
+++ b/resources/extruders/raise3D_N2_dual_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "raise3D_N2_dual_extruder_1",
"version": 2,
"name": "Right Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/raise3D_N2_plus_dual_extruder_0.def.json b/resources/extruders/raise3D_N2_plus_dual_extruder_0.def.json
index fc7531cf1b..d8821204f0 100644
--- a/resources/extruders/raise3D_N2_plus_dual_extruder_0.def.json
+++ b/resources/extruders/raise3D_N2_plus_dual_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "raise3D_N2_plus_dual_extruder_0",
"version": 2,
"name": "Left Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/raise3D_N2_plus_dual_extruder_1.def.json b/resources/extruders/raise3D_N2_plus_dual_extruder_1.def.json
index 83f949bb22..0a6ded63a3 100644
--- a/resources/extruders/raise3D_N2_plus_dual_extruder_1.def.json
+++ b/resources/extruders/raise3D_N2_plus_dual_extruder_1.def.json
@@ -1,5 +1,4 @@
{
- "id": "raise3D_N2_plus_dual_extruder_1",
"version": 2,
"name": "Right Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/raise3D_N2_single_extruder_0.def.json b/resources/extruders/raise3D_N2_single_extruder_0.def.json
index 08fedff99c..399d577110 100644
--- a/resources/extruders/raise3D_N2_single_extruder_0.def.json
+++ b/resources/extruders/raise3D_N2_single_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "raise3D_N2_single_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/renkforce_rf100_extruder_0.def.json b/resources/extruders/renkforce_rf100_extruder_0.def.json
index 6a7f883309..ff64e2f86a 100644
--- a/resources/extruders/renkforce_rf100_extruder_0.def.json
+++ b/resources/extruders/renkforce_rf100_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "renkforce_rf100_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigid3d_3rdgen_extruder_0.def.json b/resources/extruders/rigid3d_3rdgen_extruder_0.def.json
index e309086a72..edc87f695e 100644
--- a/resources/extruders/rigid3d_3rdgen_extruder_0.def.json
+++ b/resources/extruders/rigid3d_3rdgen_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigid3d_3rdgen_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigid3d_extruder_0.def.json b/resources/extruders/rigid3d_extruder_0.def.json
index e34987cd6e..eaac6b16a0 100644
--- a/resources/extruders/rigid3d_extruder_0.def.json
+++ b/resources/extruders/rigid3d_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigid3d_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigid3d_hobby_extruder_0.def.json b/resources/extruders/rigid3d_hobby_extruder_0.def.json
index 681aeecb43..68dd523af3 100644
--- a/resources/extruders/rigid3d_hobby_extruder_0.def.json
+++ b/resources/extruders/rigid3d_hobby_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigid3d_hobby_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigid3d_mucit_extruder_0.def.json b/resources/extruders/rigid3d_mucit_extruder_0.def.json
index af3f54e150..de72db7a33 100644
--- a/resources/extruders/rigid3d_mucit_extruder_0.def.json
+++ b/resources/extruders/rigid3d_mucit_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigid3d_mucit_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigid3d_zero2_extruder_0.def.json b/resources/extruders/rigid3d_zero2_extruder_0.def.json
index 30d1dbb3c4..051ce2384d 100644
--- a/resources/extruders/rigid3d_zero2_extruder_0.def.json
+++ b/resources/extruders/rigid3d_zero2_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigid3d_zero2_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigid3d_zero_extruder_0.def.json b/resources/extruders/rigid3d_zero_extruder_0.def.json
index 6c5ae10ddb..76a8fceaae 100644
--- a/resources/extruders/rigid3d_zero_extruder_0.def.json
+++ b/resources/extruders/rigid3d_zero_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigid3d_zero_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigidbot_big_extruder_0.def.json b/resources/extruders/rigidbot_big_extruder_0.def.json
index 2b07adaaaa..9ef72d5203 100644
--- a/resources/extruders/rigidbot_big_extruder_0.def.json
+++ b/resources/extruders/rigidbot_big_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigidbot_big_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/rigidbot_extruder_0.def.json b/resources/extruders/rigidbot_extruder_0.def.json
index 32ce3fc1c3..9155be0ff1 100644
--- a/resources/extruders/rigidbot_extruder_0.def.json
+++ b/resources/extruders/rigidbot_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "rigidbot_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/robo_3d_r1_extruder_0.def.json b/resources/extruders/robo_3d_r1_extruder_0.def.json
index 0872e91a11..60811842ac 100644
--- a/resources/extruders/robo_3d_r1_extruder_0.def.json
+++ b/resources/extruders/robo_3d_r1_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "robo_3d_r1_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/seemecnc_artemis_extruder_0.def.json b/resources/extruders/seemecnc_artemis_extruder_0.def.json
index a709a80cbf..a86e5eb2bd 100644
--- a/resources/extruders/seemecnc_artemis_extruder_0.def.json
+++ b/resources/extruders/seemecnc_artemis_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "seemecnc_artemis_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/seemecnc_v32_extruder_0.def.json b/resources/extruders/seemecnc_v32_extruder_0.def.json
index 5bd489e537..b223116be3 100644
--- a/resources/extruders/seemecnc_v32_extruder_0.def.json
+++ b/resources/extruders/seemecnc_v32_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "seemecnc_v32_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/skriware_2_extruder_0.def.json b/resources/extruders/skriware_2_extruder_0.def.json
new file mode 100644
index 0000000000..0569600094
--- /dev/null
+++ b/resources/extruders/skriware_2_extruder_0.def.json
@@ -0,0 +1,18 @@
+{
+ "version": 2,
+ "name": "Left Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "skriware_2",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/skriware_2_extruder_1.def.json b/resources/extruders/skriware_2_extruder_1.def.json
new file mode 100644
index 0000000000..d6fa76e1a0
--- /dev/null
+++ b/resources/extruders/skriware_2_extruder_1.def.json
@@ -0,0 +1,18 @@
+{
+ "version": 2,
+ "name": "Right Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "skriware_2",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/stereotech_start_extruder_0.def.json b/resources/extruders/stereotech_start_extruder_0.def.json
new file mode 100644
index 0000000000..b0a1e91d1c
--- /dev/null
+++ b/resources/extruders/stereotech_start_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "stereotech_start",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/stereotech_ste320_1st.def.json b/resources/extruders/stereotech_ste320_1st.def.json
new file mode 100644
index 0000000000..8110775d33
--- /dev/null
+++ b/resources/extruders/stereotech_ste320_1st.def.json
@@ -0,0 +1,45 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "stereotech_ste320",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": 0.0
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": 0.0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_extruder_start_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_start_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_start_pos_y": {
+ "value": "prime_tower_position_y"
+ },
+ "machine_extruder_end_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_end_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_end_pos_y": {
+ "value": "prime_tower_position_y"
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/stereotech_ste320_2nd.def.json b/resources/extruders/stereotech_ste320_2nd.def.json
new file mode 100644
index 0000000000..12a1479164
--- /dev/null
+++ b/resources/extruders/stereotech_ste320_2nd.def.json
@@ -0,0 +1,45 @@
+{
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "stereotech_ste320",
+ "position": "1"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": 18.0
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": 0.0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "machine_extruder_start_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_start_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_start_pos_y": {
+ "value": "prime_tower_position_y"
+ },
+ "machine_extruder_end_pos_abs": {
+ "default_value": true
+ },
+ "machine_extruder_end_pos_x": {
+ "value": "prime_tower_position_x"
+ },
+ "machine_extruder_end_pos_y": {
+ "value": "prime_tower_position_y"
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/strateo3d_left_extruder.def.json b/resources/extruders/strateo3d_left_extruder.def.json
new file mode 100644
index 0000000000..096b265030
--- /dev/null
+++ b/resources/extruders/strateo3d_left_extruder.def.json
@@ -0,0 +1,16 @@
+{
+ "version": 2,
+ "name": "Left Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "strateo3d",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 1, "maximum_value": "1" },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0 }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/strateo3d_right_extruder.def.json b/resources/extruders/strateo3d_right_extruder.def.json
new file mode 100644
index 0000000000..24acdef8b5
--- /dev/null
+++ b/resources/extruders/strateo3d_right_extruder.def.json
@@ -0,0 +1,16 @@
+{
+ "version": 2,
+ "name": "Right Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "strateo3d",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0, "maximum_value": "1" },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0 }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/structur3d_discov3ry1_complete_um2plus_extruder_0.def.json b/resources/extruders/structur3d_discov3ry1_complete_um2plus_extruder_0.def.json
index 8436dc0a94..c63f740f11 100644
--- a/resources/extruders/structur3d_discov3ry1_complete_um2plus_extruder_0.def.json
+++ b/resources/extruders/structur3d_discov3ry1_complete_um2plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "structur3d_discov3ry1_complete_um2plus_extruder_0",
"version": 2,
"name": "Discov3ry Extruder",
"inherits": "fdmextruder",
diff --git a/resources/extruders/tam_extruder_0.def.json b/resources/extruders/tam_extruder_0.def.json
index fc53efad3f..f487a6ff90 100644
--- a/resources/extruders/tam_extruder_0.def.json
+++ b/resources/extruders/tam_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "tam_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/tevo_blackwidow_extruder_0.def.json b/resources/extruders/tevo_blackwidow_extruder_0.def.json
index 125cf19c98..3450b36ac6 100644
--- a/resources/extruders/tevo_blackwidow_extruder_0.def.json
+++ b/resources/extruders/tevo_blackwidow_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "tevo_blackwidow_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/tevo_tarantula_extruder_0.def.json b/resources/extruders/tevo_tarantula_extruder_0.def.json
index bc43986814..a2ac48c06d 100644
--- a/resources/extruders/tevo_tarantula_extruder_0.def.json
+++ b/resources/extruders/tevo_tarantula_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "tevo_tarantula_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/tevo_tornado_extruder_0.def.json b/resources/extruders/tevo_tornado_extruder_0.def.json
index b47a757113..6c0c9f39b1 100644
--- a/resources/extruders/tevo_tornado_extruder_0.def.json
+++ b/resources/extruders/tevo_tornado_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "tevo_tornado_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/tizyx_evy_dual_extruder_0.def.JSON b/resources/extruders/tizyx_evy_dual_extruder_0.def.JSON
new file mode 100644
index 0000000000..282d9d2651
--- /dev/null
+++ b/resources/extruders/tizyx_evy_dual_extruder_0.def.JSON
@@ -0,0 +1,17 @@
+{
+ "version": 2,
+ "name": "Classic Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "tizyx_evy_dual",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/tizyx_evy_dual_extruder_1.def.JSON b/resources/extruders/tizyx_evy_dual_extruder_1.def.JSON
new file mode 100644
index 0000000000..69e4a60952
--- /dev/null
+++ b/resources/extruders/tizyx_evy_dual_extruder_1.def.JSON
@@ -0,0 +1,17 @@
+{
+ "version": 2,
+ "name": "Direct Drive",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "tizyx_evy_dual",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/tizyx_evy_extruder_0.def.JSON b/resources/extruders/tizyx_evy_extruder_0.def.JSON
index bd3c4c9792..4f93648491 100644
--- a/resources/extruders/tizyx_evy_extruder_0.def.JSON
+++ b/resources/extruders/tizyx_evy_extruder_0.def.JSON
@@ -1,5 +1,4 @@
{
- "id": "tizyx_evy_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/tizyx_k25_extruder_0.def.json b/resources/extruders/tizyx_k25_extruder_0.def.json
index 409198d77c..626fedf434 100644
--- a/resources/extruders/tizyx_k25_extruder_0.def.json
+++ b/resources/extruders/tizyx_k25_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "tizyx_k25_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ubuild-3d_mr_bot_280_extruder_0.def.json b/resources/extruders/ubuild-3d_mr_bot_280_extruder_0.def.json
index b04ca0dcbf..749a5ed77d 100644
--- a/resources/extruders/ubuild-3d_mr_bot_280_extruder_0.def.json
+++ b/resources/extruders/ubuild-3d_mr_bot_280_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ubuild-3d_mr_bot_280_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker2_extended_extruder_0.def.json b/resources/extruders/ultimaker2_extended_extruder_0.def.json
index 6387ec72ed..cc7306a393 100644
--- a/resources/extruders/ultimaker2_extended_extruder_0.def.json
+++ b/resources/extruders/ultimaker2_extended_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker2_extended_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker2_extended_plus_extruder_0.def.json b/resources/extruders/ultimaker2_extended_plus_extruder_0.def.json
index 39fc665ff2..337c120097 100644
--- a/resources/extruders/ultimaker2_extended_plus_extruder_0.def.json
+++ b/resources/extruders/ultimaker2_extended_plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker2_extended_plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker2_extruder_0.def.json b/resources/extruders/ultimaker2_extruder_0.def.json
index 2daf57c73f..64ac8698f1 100644
--- a/resources/extruders/ultimaker2_extruder_0.def.json
+++ b/resources/extruders/ultimaker2_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker2_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker2_go_extruder_0.def.json b/resources/extruders/ultimaker2_go_extruder_0.def.json
index 4c258e237e..5ddcfbd551 100644
--- a/resources/extruders/ultimaker2_go_extruder_0.def.json
+++ b/resources/extruders/ultimaker2_go_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker2_go_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker2_plus_extruder_0.def.json b/resources/extruders/ultimaker2_plus_extruder_0.def.json
index 13ab0c59ea..abf36c0b08 100644
--- a/resources/extruders/ultimaker2_plus_extruder_0.def.json
+++ b/resources/extruders/ultimaker2_plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker2_plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker3_extended_extruder_left.def.json b/resources/extruders/ultimaker3_extended_extruder_left.def.json
index 2d81424bc6..fbc49a1f32 100644
--- a/resources/extruders/ultimaker3_extended_extruder_left.def.json
+++ b/resources/extruders/ultimaker3_extended_extruder_left.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker3_extended_extruder_left",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker3_extended_extruder_right.def.json b/resources/extruders/ultimaker3_extended_extruder_right.def.json
index 7cdd5876c1..fbe6bcc878 100644
--- a/resources/extruders/ultimaker3_extended_extruder_right.def.json
+++ b/resources/extruders/ultimaker3_extended_extruder_right.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker3_extended_extruder_right",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker3_extruder_left.def.json b/resources/extruders/ultimaker3_extruder_left.def.json
index 9f5ed34692..b18e2decfa 100644
--- a/resources/extruders/ultimaker3_extruder_left.def.json
+++ b/resources/extruders/ultimaker3_extruder_left.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker3_extruder_left",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker3_extruder_right.def.json b/resources/extruders/ultimaker3_extruder_right.def.json
index 7298a552b7..4753fde489 100644
--- a/resources/extruders/ultimaker3_extruder_right.def.json
+++ b/resources/extruders/ultimaker3_extruder_right.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker3_extruder_right",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker_original_dual_1st.def.json b/resources/extruders/ultimaker_original_dual_1st.def.json
index 3d837fc989..acc8168d94 100644
--- a/resources/extruders/ultimaker_original_dual_1st.def.json
+++ b/resources/extruders/ultimaker_original_dual_1st.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_original_dual_1st",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker_original_dual_2nd.def.json b/resources/extruders/ultimaker_original_dual_2nd.def.json
index 80cc17c58d..7907571e66 100644
--- a/resources/extruders/ultimaker_original_dual_2nd.def.json
+++ b/resources/extruders/ultimaker_original_dual_2nd.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_original_dual_2nd",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker_original_extruder_0.def.json b/resources/extruders/ultimaker_original_extruder_0.def.json
index 4aab693212..30df96df58 100644
--- a/resources/extruders/ultimaker_original_extruder_0.def.json
+++ b/resources/extruders/ultimaker_original_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_original_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker_original_plus_extruder_0.def.json b/resources/extruders/ultimaker_original_plus_extruder_0.def.json
index 91d0751861..fec40e93a9 100644
--- a/resources/extruders/ultimaker_original_plus_extruder_0.def.json
+++ b/resources/extruders/ultimaker_original_plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_original_plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker_s3_extruder_left.def.json b/resources/extruders/ultimaker_s3_extruder_left.def.json
new file mode 100644
index 0000000000..7af6f7d0dc
--- /dev/null
+++ b/resources/extruders/ultimaker_s3_extruder_left.def.json
@@ -0,0 +1,29 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "ultimaker_s3",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": { "default_value": 0 },
+ "machine_nozzle_offset_y": { "default_value": 0 },
+
+ "machine_extruder_start_pos_abs": { "default_value": true },
+ "machine_extruder_start_pos_x": { "default_value": 180 },
+ "machine_extruder_start_pos_y": { "default_value": 180 },
+ "machine_extruder_end_pos_abs": { "default_value": true },
+ "machine_extruder_end_pos_x": { "default_value": 180 },
+ "machine_extruder_end_pos_y": { "default_value": 180 },
+ "machine_nozzle_head_distance": { "default_value": 2.7 },
+ "extruder_prime_pos_x": { "default_value": -3 },
+ "extruder_prime_pos_y": { "default_value": 6 },
+ "extruder_prime_pos_z": { "default_value": 2 }
+ }
+}
diff --git a/resources/extruders/ultimaker_s3_extruder_right.def.json b/resources/extruders/ultimaker_s3_extruder_right.def.json
new file mode 100644
index 0000000000..7199710327
--- /dev/null
+++ b/resources/extruders/ultimaker_s3_extruder_right.def.json
@@ -0,0 +1,29 @@
+{
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "ultimaker_s3",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 1,
+ "maximum_value": "1"
+ },
+ "machine_nozzle_offset_x": { "default_value": 22 },
+ "machine_nozzle_offset_y": { "default_value": 0 },
+
+ "machine_extruder_start_pos_abs": { "default_value": true },
+ "machine_extruder_start_pos_x": { "default_value": 180 },
+ "machine_extruder_start_pos_y": { "default_value": 180 },
+ "machine_extruder_end_pos_abs": { "default_value": true },
+ "machine_extruder_end_pos_x": { "default_value": 180 },
+ "machine_extruder_end_pos_y": { "default_value": 180 },
+ "machine_nozzle_head_distance": { "default_value": 4.2 },
+ "extruder_prime_pos_x": { "value": "machine_width + 3" },
+ "extruder_prime_pos_y": { "default_value": 6 },
+ "extruder_prime_pos_z": { "default_value": 2 }
+ }
+}
diff --git a/resources/extruders/ultimaker_s5_extruder_left.def.json b/resources/extruders/ultimaker_s5_extruder_left.def.json
index 275f60bb31..24de85e9cc 100644
--- a/resources/extruders/ultimaker_s5_extruder_left.def.json
+++ b/resources/extruders/ultimaker_s5_extruder_left.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_s5_extruder_left",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/ultimaker_s5_extruder_right.def.json b/resources/extruders/ultimaker_s5_extruder_right.def.json
index 92e08f5cc5..1e0ac3eace 100644
--- a/resources/extruders/ultimaker_s5_extruder_right.def.json
+++ b/resources/extruders/ultimaker_s5_extruder_right.def.json
@@ -1,5 +1,4 @@
{
- "id": "ultimaker_s5_extruder_right",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/uni_print_3d_extruder_0.def.json b/resources/extruders/uni_print_3d_extruder_0.def.json
index d0711fd458..747fb9e020 100644
--- a/resources/extruders/uni_print_3d_extruder_0.def.json
+++ b/resources/extruders/uni_print_3d_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "uni_print_3d_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/uniqbot_one_extruder_0.def.json b/resources/extruders/uniqbot_one_extruder_0.def.json
index 65436ee789..0a8982559d 100644
--- a/resources/extruders/uniqbot_one_extruder_0.def.json
+++ b/resources/extruders/uniqbot_one_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "uniqbot_one_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/vertex_delta_k8800_extruder_0.def.json b/resources/extruders/vertex_delta_k8800_extruder_0.def.json
index 5e09046faf..05a010222f 100644
--- a/resources/extruders/vertex_delta_k8800_extruder_0.def.json
+++ b/resources/extruders/vertex_delta_k8800_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "vertex_delta_k8800_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/vertex_k8400_dual_1st.def.json b/resources/extruders/vertex_k8400_dual_1st.def.json
index 86fb2266ba..947cfbc7d8 100644
--- a/resources/extruders/vertex_k8400_dual_1st.def.json
+++ b/resources/extruders/vertex_k8400_dual_1st.def.json
@@ -1,5 +1,4 @@
{
- "id": "vertex_k8400_dual_1st",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/vertex_k8400_dual_2nd.def.json b/resources/extruders/vertex_k8400_dual_2nd.def.json
index 306b2dcb7a..e606e46337 100644
--- a/resources/extruders/vertex_k8400_dual_2nd.def.json
+++ b/resources/extruders/vertex_k8400_dual_2nd.def.json
@@ -1,5 +1,4 @@
{
- "id": "vertex_k8400_dual_2nd",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
diff --git a/resources/extruders/vertex_k8400_extruder_0.def.json b/resources/extruders/vertex_k8400_extruder_0.def.json
index c03453b519..e0304f57bd 100644
--- a/resources/extruders/vertex_k8400_extruder_0.def.json
+++ b/resources/extruders/vertex_k8400_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "vertex_k8400_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/vertex_nano_k8600_extruder_0.def.json b/resources/extruders/vertex_nano_k8600_extruder_0.def.json
new file mode 100644
index 0000000000..cfb2d11217
--- /dev/null
+++ b/resources/extruders/vertex_nano_k8600_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "vertex_nano_k8600",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.35 },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
diff --git a/resources/extruders/wanhao_d4s_extruder_0.def.json b/resources/extruders/wanhao_d4s_extruder_0.def.json
index 9a750e072c..bd6023faf4 100644
--- a/resources/extruders/wanhao_d4s_extruder_0.def.json
+++ b/resources/extruders/wanhao_d4s_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_d4s_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_d6_extruder_0.def.json b/resources/extruders/wanhao_d6_extruder_0.def.json
index a8a3bf15d3..093546eabf 100644
--- a/resources/extruders/wanhao_d6_extruder_0.def.json
+++ b/resources/extruders/wanhao_d6_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_d6_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_d6_plus_extruder_0.def.json b/resources/extruders/wanhao_d6_plus_extruder_0.def.json
index b2b1e6ab05..acc5b66072 100644
--- a/resources/extruders/wanhao_d6_plus_extruder_0.def.json
+++ b/resources/extruders/wanhao_d6_plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_d6_plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_d9_extruder_0.def.json b/resources/extruders/wanhao_d9_extruder_0.def.json
index 76d501e5a2..40fcf422f5 100644
--- a/resources/extruders/wanhao_d9_extruder_0.def.json
+++ b/resources/extruders/wanhao_d9_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_d9_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_duplicator5S_extruder_0.def.json b/resources/extruders/wanhao_duplicator5S_extruder_0.def.json
index 74f47158a3..7274d5117e 100644
--- a/resources/extruders/wanhao_duplicator5S_extruder_0.def.json
+++ b/resources/extruders/wanhao_duplicator5S_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_duplicator5S_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_duplicator5Smini_extruder_0.def.json b/resources/extruders/wanhao_duplicator5Smini_extruder_0.def.json
index 8c91de4685..3479c94e35 100644
--- a/resources/extruders/wanhao_duplicator5Smini_extruder_0.def.json
+++ b/resources/extruders/wanhao_duplicator5Smini_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_duplicator5Smini_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_i3_extruder_0.def.json b/resources/extruders/wanhao_i3_extruder_0.def.json
index 7d881079c4..387a456ff2 100644
--- a/resources/extruders/wanhao_i3_extruder_0.def.json
+++ b/resources/extruders/wanhao_i3_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_i3_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_i3mini_extruder_0.def.json b/resources/extruders/wanhao_i3mini_extruder_0.def.json
index c5abbd175e..2d52f0d126 100644
--- a/resources/extruders/wanhao_i3mini_extruder_0.def.json
+++ b/resources/extruders/wanhao_i3mini_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_i3mini_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/wanhao_i3plus_extruder_0.def.json b/resources/extruders/wanhao_i3plus_extruder_0.def.json
index 0dae64ce63..103e3b9335 100644
--- a/resources/extruders/wanhao_i3plus_extruder_0.def.json
+++ b/resources/extruders/wanhao_i3plus_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "wanhao_i3plus_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/z-bolt_extruder_0.def.json b/resources/extruders/z-bolt_extruder_0.def.json
index 70e9f6177c..04c8d10cbb 100644
--- a/resources/extruders/z-bolt_extruder_0.def.json
+++ b/resources/extruders/z-bolt_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "z-bolt_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/zone3d_printer_extruder_0.def.json b/resources/extruders/zone3d_printer_extruder_0.def.json
index ca024dd5c4..fb8f40d3e2 100644
--- a/resources/extruders/zone3d_printer_extruder_0.def.json
+++ b/resources/extruders/zone3d_printer_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "zone3d_printer_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/extruders/zyyx_agile_extruder_0.def.json b/resources/extruders/zyyx_agile_extruder_0.def.json
index edda9b3097..c01ffb59f3 100644
--- a/resources/extruders/zyyx_agile_extruder_0.def.json
+++ b/resources/extruders/zyyx_agile_extruder_0.def.json
@@ -1,5 +1,4 @@
{
- "id": "zyyx_agile_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
diff --git a/resources/i18n/cura.pot b/resources/i18n/cura.pot
index 749fdb65ee..40a0c03721 100644
--- a/resources/i18n/cura.pot
+++ b/resources/i18n/cura.pot
@@ -8,17 +8,17 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"Language: \n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr ""
@@ -40,13 +40,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr ""
@@ -56,7 +56,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -69,71 +69,52 @@ msgid ""
"guide
"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Changelog"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
msgctxt "@action"
msgid "Update Firmware"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
-msgctxt "@item:inmenu"
-msgid "Flatten active settings"
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:35
-msgctxt "@info:status"
-msgid "Profile has been flattened & activated."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:33
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:34
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:43
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:35
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:44
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:71
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:80
msgctxt "@info:status"
msgid "Connected via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:96
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:105
msgctxt "@label"
msgid ""
"A USB print is in progress, closing Cura will stop this print. Are you sure?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/install/X3GWriter/__init__.py:15
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
-msgctxt "X3G Writer File Description"
-msgid "X3G File"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid ""
+"A print is still in progress. Cura cannot start another print via USB until "
+"the previous print has completed."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
-msgctxt "X3g Writer Plugin Description"
-msgid "Writes X3g to files"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:21
-msgctxt "X3g Writer File Description"
-msgid "X3g File"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "Print in Progress"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
@@ -148,6 +129,7 @@ msgid "GCodeGzWriter does not support text mode."
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:28
+#: /home/ruben/Projects/Cura/plugins/UFPReader/__init__.py:22
msgctxt "@item:inlistbox"
msgid "Ultimaker Format Package"
msgstr ""
@@ -169,7 +151,7 @@ msgid "Save to Removable Drive {0}"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:107
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr ""
@@ -206,10 +188,9 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:152
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1629
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:139
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1668
msgctxt "@info:title"
msgid "Error"
msgstr ""
@@ -238,9 +219,9 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:151
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:163
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1619
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1719
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1658
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1758
msgctxt "@info:title"
msgid "Warning"
msgstr ""
@@ -267,344 +248,164 @@ msgctxt "@item:intext"
msgid "Removable Drive"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:74
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py:26
+msgctxt "@action"
+msgid "Connect via Network"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:57
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:58
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
-msgctxt "@info:status"
-msgid "Connected over the network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
-msgctxt "@info:status"
-msgid ""
-"Connected over the network. Please approve the access request on the printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:93
-msgctxt "@info:status"
-msgid "Connected over the network. No access to control the printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
-msgctxt "@info:status"
-msgid ""
-"Access to the printer requested. Please approve the request on the printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:101
-msgctxt "@info:title"
-msgid "Authentication status"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
-msgctxt "@info:title"
-msgid "Authentication Status"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:187
-msgctxt "@action:button"
-msgid "Retry"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
-msgctxt "@info:tooltip"
-msgid "Re-send the access request"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
-msgctxt "@info:status"
-msgid "Access to the printer accepted"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
-msgctxt "@info:status"
-msgid "No access to print with this printer. Unable to send print job."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:65
-msgctxt "@action:button"
-msgid "Request Access"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:66
-msgctxt "@info:tooltip"
-msgid "Send access request to the printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:201
-msgctxt "@label"
-msgid "Unable to start a new print job."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:203
-msgctxt "@label"
-msgid ""
-"There is an issue with the configuration of your Ultimaker, which makes it "
-"impossible to start the print. Please resolve this issues before continuing."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:209
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:231
-msgctxt "@window:title"
-msgid "Mismatched configuration"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:223
-msgctxt "@label"
-msgid "Are you sure you wish to print with the selected configuration?"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:225
-msgctxt "@label"
-msgid ""
-"There is a mismatch between the configuration or calibration of the printer "
-"and Cura. For the best result, always slice for the PrintCores and materials "
-"that are inserted in your printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:252
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:162
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:162
-msgctxt "@info:status"
-msgid ""
-"Sending new jobs (temporarily) blocked, still sending the previous print job."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:180
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
-msgctxt "@info:status"
-msgid "Sending data to printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:182
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:199
-msgctxt "@info:title"
-msgid "Sending Data"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:200
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:395
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:38
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:391
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:254
-msgctxt "@action:button"
-msgid "Cancel"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:324
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:330
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No material loaded in slot {slot_number}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:353
-#, python-brace-format
-msgctxt "@label"
-msgid ""
-"Different PrintCore (Cura: {cura_printcore_name}, Printer: "
-"{remote_printcore_name}) selected for extruder {extruder_id}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:362
-#, python-brace-format
-msgctxt "@label"
-msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:548
-msgctxt "@window:title"
-msgid "Sync with your printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:550
-msgctxt "@label"
-msgid "Would you like to use your current printer configuration in Cura?"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:552
-msgctxt "@label"
-msgid ""
-"The PrintCores and/or materials on your printer differ from those within "
-"your current project. For the best result, always slice for the PrintCores "
-"and materials that are inserted in your printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:59
msgctxt "@info:status"
msgid "Connected over the network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:275
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:342
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:15
msgctxt "@info:status"
-msgid "Print job was successfully sent to the printer."
+msgid "Please wait until the current job has been sent."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:277
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:343
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:16
msgctxt "@info:title"
-msgid "Data Sent"
+msgid "Print error"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:278
-msgctxt "@action:button"
-msgid "View in Monitor"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:21
+msgctxt "@info:title"
+msgid "New cloud printers found"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:390
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:290
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:22
+msgctxt "@info:message"
+msgid ""
+"New printers have been found connected to your account, you can find them in "
+"your list of discovered printers."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:27
+msgctxt "@info:option_text"
+msgid "Do not show this message again"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:27
#, python-brace-format
msgctxt "@info:status"
-msgid "Printer '{printer_name}' has finished printing '{job_name}'."
+msgid ""
+"You are attempting to connect to {0} but it is not the host of a group. You "
+"can visit the web page to configure it as a group host."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:392
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:294
-#, python-brace-format
-msgctxt "@info:status"
-msgid "The print job '{job_name}' was finished."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:393
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:289
-msgctxt "@info:status"
-msgid "Print finished"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:573
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:607
-msgctxt "@label:material"
-msgid "Empty"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:574
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:608
-msgctxt "@label:material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:151
-msgctxt "@action:button"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:152
-msgctxt "@properties:tooltip"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:153
-msgctxt "@info:status"
-msgid "Connected via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:163
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:30
msgctxt "@info:title"
-msgid "Cloud error"
+msgid "Not a group host"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:180
-msgctxt "@info:status"
-msgid "Could not export print job."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:35
+msgctxt "@action"
+msgid "Configure group"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:330
-msgctxt "@info:text"
-msgid "Could not upload the data to the printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
-msgctxt "@info:status"
-msgid "tomorrow"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
-msgctxt "@info:status"
-msgid "today"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:151
-msgctxt "@info:description"
-msgid "There was an error connecting to the cloud."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
-msgctxt "@info:status"
-msgid "Sending data to remote cluster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:456
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:27
msgctxt "@info:status"
msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:460
-msgctxt "@info:status"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:33
+msgctxt "@info:status Ultimaker Cloud should not be translated."
msgid "Connect to Ultimaker Cloud"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:461
-msgctxt "@action"
-msgid "Don't ask me again for this printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:464
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:36
msgctxt "@action"
msgid "Get started"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:478
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading print job to printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:15
+msgctxt "@info:status"
+msgid "Print job was successfully sent to the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:16
+msgctxt "@info:title"
+msgid "Data Sent"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:18
msgctxt "@info:status"
msgid ""
-"You can now send and monitor print jobs from anywhere using your Ultimaker "
-"account."
+"You are attempting to connect to a printer that is not running Ultimaker "
+"Connect. Please update the printer to the latest firmware."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:482
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:21
+msgctxt "@info:title"
+msgid "Update your printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:24
+#, python-brace-format
msgctxt "@info:status"
-msgid "Connected!"
+msgid ""
+"Cura has detected material profiles that were not yet installed on the host "
+"printer of group {0}."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:486
-msgctxt "@action"
-msgid "Review your connection"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:26
+msgctxt "@info:title"
+msgid "Sending materials to printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
-msgctxt "@action"
-msgid "Connect via Network"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:15
+msgctxt "@info:text"
+msgid "Could not upload the data to the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:16
+msgctxt "@info:title"
+msgid "Network error"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:27
+msgctxt "@info:status"
+msgid "tomorrow"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:30
+msgctxt "@info:status"
+msgid "today"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:138
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:139
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:140
+msgctxt "@info:status"
+msgid "Connected via Cloud"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
@@ -612,7 +413,7 @@ msgctxt "@item:inmenu"
msgid "Monitor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:124
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:125
msgctxt "@info"
msgid "Could not access update information."
msgstr ""
@@ -643,12 +444,12 @@ msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:117
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:118
msgctxt "@info:title"
msgid "Simulation View"
msgstr ""
@@ -673,49 +474,11 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:55
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:57
-msgctxt "@action:button"
-msgid "More info"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:58
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:60
-msgctxt "@action:button"
-msgid "Allow"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:61
-msgctxt "@action:tooltip"
-msgid ""
-"Allow Cura to send anonymized usage statistics to help prioritize future "
-"improvements to Cura. Some of your preferences and settings are sent, the "
-"Cura version and a hash of the models you're slicing."
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/R2D2/__init__.py:17
-msgctxt "@item:inmenu"
-msgid "Evaluation"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/ImageReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "JPG Image"
@@ -741,24 +504,54 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:15
+msgctxt "@item:inlistbox 'Open' is part of the name of this file format."
+msgid "Open Compressed Triangle Mesh"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:19
+msgctxt "@item:inlistbox"
+msgid "COLLADA Digital Asset Exchange"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:23
+msgctxt "@item:inlistbox"
+msgid "glTF Binary"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:27
+msgctxt "@item:inlistbox"
+msgid "glTF Embedded JSON"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:36
+msgctxt "@item:inlistbox"
+msgid "Stanford Triangle Format"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:40
+msgctxt "@item:inlistbox"
+msgid "Compressed COLLADA Digital Asset Exchange"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
msgctxt "@info:status"
msgid ""
"Unable to slice with the current material as it is incompatible with the "
"selected machine or configuration."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:389
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:398
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:407
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:416
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:362
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:386
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:395
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:404
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:413
msgctxt "@info:title"
msgid "Unable to slice"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -766,7 +559,7 @@ msgid ""
"errors: {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -774,13 +567,13 @@ msgid ""
"errors on one or more models: {error_labels}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:394
msgctxt "@info:status"
msgid ""
"Unable to slice because the prime tower or prime position(s) are invalid."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid ""
@@ -788,7 +581,7 @@ msgid ""
"%s."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:412
msgctxt "@info:status"
msgid ""
"Nothing to slice because none of the models fit the build volume or are "
@@ -797,12 +590,12 @@ msgid ""
msgstr ""
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr ""
@@ -817,12 +610,12 @@ msgctxt "@info:tooltip"
msgid "Configure Per Model Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:186
msgctxt "@title:tab"
msgid "Recommended"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:188
msgctxt "@title:tab"
msgid "Custom"
msgstr ""
@@ -833,13 +626,13 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:190
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:763
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:198
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:651
msgctxt "@label"
msgid "Nozzle"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:469
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:496
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid ""
@@ -848,7 +641,7 @@ msgid ""
"instead."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:472
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:499
msgctxt "@info:title"
msgid "Open Project File"
msgstr ""
@@ -863,18 +656,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:324
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:335
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:326
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:476
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:337
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:491
msgctxt "@info:title"
msgid "G-code Details"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:474
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:489
msgctxt "@info:generic"
msgid ""
"Make sure the g-code is suitable for your printer and printer configuration "
@@ -899,7 +692,7 @@ msgctxt "@info:backup_status"
msgid "There was an error listing your backups."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:121
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:132
msgctxt "@info:backup_status"
msgid "There was an error trying to restore your backup."
msgstr ""
@@ -930,16 +723,6 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
-msgctxt "@item:inmenu"
-msgid "Profile Assistant"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
-msgctxt "@item:inlistbox"
-msgid "Profile Assistant"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:26
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -960,96 +743,39 @@ msgctxt "@item:inmenu"
msgid "Preview"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
-msgctxt "@action"
-msgid "Checkup"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:81
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:82
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:83
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:84
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:85
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:86
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:87
-msgctxt "@tooltip"
-msgid "Support"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:88
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
-msgctxt "@tooltip"
-msgid "Other"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:309
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/API/Account.py:77
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
msgctxt "@info:title"
msgid "Login failed"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:201
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:36
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:55
+msgctxt "@info:No intent profile selected"
+msgid "Default"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:196
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:125
msgctxt "@title:window"
msgid "File Already Exists"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:202
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:197
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:126
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid ""
@@ -1057,43 +783,45 @@ msgid ""
"overwrite it?"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:425
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:428
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:433
msgctxt "@info:status"
msgid "Invalid file URL:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:206
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:915
-#, python-format
-msgctxt "@info:generic"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:780
+msgctxt "@info:message Followed by a list of settings."
msgid ""
-"Settings have been changed to match the current availability of extruders: "
-"[%s]"
+"Settings have been changed to match the current availability of extruders:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:917
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:782
msgctxt "@info:title"
msgid "Settings updated"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1458
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1334
msgctxt "@info:title"
msgid "Extruder(s) Disabled"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1457
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:99
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:86
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:182
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:223
+msgctxt "@label"
+msgid "Unknown"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:137
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid ""
"Failed to export profile to {0}: {1}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:138
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid ""
@@ -1101,44 +829,44 @@ msgid ""
"failure."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:149
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:150
msgctxt "@info:title"
msgid "Export succeeded"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}: {1}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:181
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid ""
"Can't import profile from {0} before a printer is added."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:198
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "No custom profile to import in file {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:202
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:226
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:236
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid ""
@@ -1146,100 +874,248 @@ msgid ""
"import it."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:241
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:325
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid ""
-"The machine defined in profile {0} ({1}) doesn't match "
-"with your current machine ({2}), could not import it."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to import profile from {0}:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:328
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:319
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:331
#, python-brace-format
msgctxt "@info:status"
msgid "File {0} does not contain any valid profile."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:322
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:334
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:340
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:369
msgctxt "@label"
msgid "Custom profile"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:385
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:370
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:399
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:69
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:76
+msgctxt "@tooltip"
+msgid "Outer Wall"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:77
+msgctxt "@tooltip"
+msgid "Inner Walls"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:78
+msgctxt "@tooltip"
+msgid "Skin"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:79
+msgctxt "@tooltip"
+msgid "Infill"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:80
+msgctxt "@tooltip"
+msgid "Support Infill"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:81
+msgctxt "@tooltip"
+msgid "Support Interface"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:82
+msgctxt "@tooltip"
+msgid "Support"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:83
+msgctxt "@tooltip"
+msgid "Skirt"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:84
+msgctxt "@tooltip"
+msgid "Prime Tower"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:85
+msgctxt "@tooltip"
+msgid "Travel"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:86
+msgctxt "@tooltip"
+msgid "Retractions"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:87
+msgctxt "@tooltip"
+msgid "Other"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:302
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+msgctxt "@action:button"
+msgid "Next"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:62
#, python-brace-format
msgctxt "@label"
msgid "Group #{group_nr}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:65
-msgctxt "@info:title"
-msgid "Network enabled printers"
+#: /home/ruben/Projects/Cura/cura/UI/WhatsNewPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:169
+msgctxt "@action:button"
+msgid "Close"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:80
-msgctxt "@info:title"
-msgid "Local printers"
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:18
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:352
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:58
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:149
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:406
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:294
+msgctxt "@action:button"
+msgid "Cancel"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:36
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:320
+msgctxt "@label"
+msgid "Default"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:39
+msgctxt "@label"
+msgid "Visual"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:40
+msgctxt "@text"
+msgid ""
+"The visual profile is designed to print visual prototypes and models with "
+"the intent of high visual and surface quality."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:43
+msgctxt "@label"
+msgid "Engineering"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:44
+msgctxt "@text"
+msgid ""
+"The engineering profile is designed to print functional prototypes and end-"
+"use parts with the intent of better accuracy and for closer tolerances."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:47
+msgctxt "@label"
+msgid "Draft"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:48
+msgctxt "@text"
+msgid ""
+"The draft profile is designed to print initial prototypes and concept "
+"validation with the intent of significant print time reduction."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:357
+msgctxt "@label"
+msgid "Custom profiles"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:391
#, python-brace-format
msgctxt "@item:inlistbox"
msgid "All Supported Types ({0})"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:110
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:392
msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:665
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:213
msgctxt "@label"
msgid "Custom Material"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:666
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:256
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:214
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:205
msgctxt "@label"
msgid "Custom"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:116
+msgctxt "@label"
+msgid ""
+"The printer(s) below cannot be connected because they are part of a group"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:118
+msgctxt "@label"
+msgid "Available networked printers"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:90
msgctxt "@info:status"
msgid ""
"The build volume height has been reduced due to the value of the \"Print "
"Sequence\" setting to prevent the gantry from colliding with printed models."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:83
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:92
msgctxt "@info:title"
msgid "Build Volume"
msgstr ""
@@ -1254,53 +1130,67 @@ msgctxt "@info:backup_failed"
msgid "Tried to restore a Cura backup without having proper data or meta data."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:124
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:125
msgctxt "@info:backup_failed"
-msgid ""
-"Tried to restore a Cura backup that does not match your current version."
+msgid "Tried to restore a Cura backup that is higher than the current version."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
msgctxt "@info"
msgid "Unable to reach the Ultimaker account server."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:70
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:77
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:29
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:30
msgctxt "@info:title"
msgid "Placing Objects"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:149
msgctxt "@info:status"
msgid "Unable to find a location within the build volume for all objects"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
msgctxt "@info:title"
msgid "Placing Object"
msgstr ""
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:30
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:67
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:66
msgctxt "@info:status"
msgid "Finding new location for objects"
msgstr ""
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:34
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:71
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:70
msgctxt "@info:title"
msgid "Finding Location"
msgstr ""
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr ""
@@ -1430,30 +1320,37 @@ msgstr ""
#: /home/ruben/Projects/Cura/cura/CrashHandler.py:322
msgctxt "@title:groupbox"
-msgid "User description"
+msgid ""
+"User description (Note: Developers may not speak your language, please use "
+"English if possible)"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:341
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:480
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:513
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:781
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:520
+msgctxt "@info:progress"
+msgid "Setting up preferences..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:824
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:817
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:859
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1059
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1150
#, python-format
msgctxt ""
"@info 'width', 'depth' and 'height' are variable names that must NOT be "
@@ -1461,230 +1358,171 @@ msgctxt ""
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1618
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1657
#, python-brace-format
msgctxt "@info:status"
msgid "Only one G-code file can be loaded at a time. Skipped importing {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1628
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1667
#, python-brace-format
msgctxt "@info:status"
msgid "Can't open any other file if G-code is loading. Skipped importing {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1718
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1757
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:62
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:81
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:100
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:56
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:70
msgctxt "@label"
msgid "X (Width)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:112
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:122
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:132
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:387
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:429
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:441
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:897
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:74
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:88
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:102
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:243
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:265
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:285
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:79
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:93
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:109
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:124
msgctxt "@label"
msgid "mm"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:84
msgctxt "@label"
msgid "Y (Depth)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:98
msgctxt "@label"
msgid "Z (Height)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:143
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:112
msgctxt "@label"
msgid "Build plate shape"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:152
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:125
+msgctxt "@label"
msgid "Origin at center"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:160
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:137
+msgctxt "@label"
msgid "Heated bed"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:171
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:149
+msgctxt "@label"
+msgid "Heated build volume"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:161
msgctxt "@label"
msgid "G-code flavor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:184
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:185
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:199
msgctxt "@label"
msgid "X min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:195
-msgctxt "@tooltip"
-msgid ""
-"Distance from the left of the printhead to the center of the nozzle. Used to "
-"prevent colissions between previous prints and the printhead when printing "
-"\"One at a Time\"."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:219
msgctxt "@label"
msgid "Y min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:205
-msgctxt "@tooltip"
-msgid ""
-"Distance from the front of the printhead to the center of the nozzle. Used "
-"to prevent colissions between previous prints and the printhead when "
-"printing \"One at a Time\"."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:239
msgctxt "@label"
msgid "X max"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:215
-msgctxt "@tooltip"
-msgid ""
-"Distance from the right of the printhead to the center of the nozzle. Used "
-"to prevent colissions between previous prints and the printhead when "
-"printing \"One at a Time\"."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:261
msgctxt "@label"
msgid "Y max"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:225
-msgctxt "@tooltip"
-msgid ""
-"Distance from the rear of the printhead to the center of the nozzle. Used to "
-"prevent colissions between previous prints and the printhead when printing "
-"\"One at a Time\"."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:281
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:239
-msgctxt "@tooltip"
-msgid ""
-"The height difference between the tip of the nozzle and the gantry system (X "
-"and Y axes). Used to prevent collisions between previous prints and the "
-"gantry when printing \"One at a Time\"."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:258
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:295
msgctxt "@label"
msgid "Number of Extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:314
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:324
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:333
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:366
+msgctxt "@title:label"
msgid "End G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:343
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very end."
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:42
+msgctxt "@title:tab"
+msgid "Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:374
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:63
+msgctxt "@title:label"
msgid "Nozzle Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:404
-msgctxt "@tooltip"
-msgid ""
-"The nominal diameter of filament supported by the printer. The exact "
-"diameter will be overridden by the material and/or the profile."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:428
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:440
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:120
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:452
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:135
msgctxt "@label"
msgid "Cooling Fan Number"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:453
-msgctxt "@label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:473
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:491
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr ""
@@ -1694,7 +1532,7 @@ msgid "Install"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr ""
@@ -1710,16 +1548,16 @@ msgctxt "@label"
msgid "ratings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:28
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:32
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:30
msgctxt "@title:tab"
msgid "Plugins"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:69
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:42
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:361
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:77
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr ""
@@ -1729,52 +1567,49 @@ msgctxt "@label"
msgid "Your rating"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:98
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:99
msgctxt "@label"
msgid "Version"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:105
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:106
msgctxt "@label"
msgid "Last updated"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:112
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:260
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:113
msgctxt "@label"
msgid "Author"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:119
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:120
msgctxt "@label"
msgid "Downloads"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:181
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:222
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:265
-msgctxt "@label"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:56
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to install or update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:73
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:80
+msgctxt "@label:The string between and is the highlighted link"
+msgid "Buy material spools"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:96
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:34
msgctxt "@action:button"
msgid "Update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:74
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:97
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:35
msgctxt "@action:button"
msgid "Updating"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:75
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:98
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:36
msgctxt "@action:button"
msgid "Updated"
@@ -1837,22 +1672,22 @@ msgctxt "@info:button"
msgid "Quit Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Contributions"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Plugins"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:43
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:40
msgctxt "@label"
msgid "Generic Materials"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:56
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr ""
@@ -1905,27 +1740,47 @@ msgctxt "@label"
msgid "Featured"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:34
msgctxt "@label"
msgid "Compatibility"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:124
+msgctxt "@label:table_header"
+msgid "Machine"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:137
+msgctxt "@label:table_header"
+msgid "Build Plate"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:143
+msgctxt "@label:table_header"
+msgid "Support"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:149
+msgctxt "@label:table_header"
+msgid "Quality"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:170
msgctxt "@action:label"
msgid "Technical Data Sheet"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:179
msgctxt "@action:label"
msgid "Safety Data Sheet"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:188
msgctxt "@action:label"
msgid "Printing Guidelines"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:197
msgctxt "@action:label"
msgid "Website"
msgstr ""
@@ -1935,12 +1790,12 @@ msgctxt "@info"
msgid "Fetching packages..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:90
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:91
msgctxt "@label"
msgid "Website"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:97
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr ""
@@ -1952,22 +1807,6 @@ msgid ""
"adjustment."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
-msgctxt "@label"
-msgid "Changelog"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:85
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
-msgctxt "@action:button"
-msgid "Close"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
msgctxt "@title"
msgid "Update Firmware"
@@ -2051,59 +1890,66 @@ msgctxt "@label"
msgid "Firmware update failed due to missing firmware."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UserAgreement/UserAgreement.qml:16
-msgctxt "@title:window"
-msgid "User Agreement"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:155
+msgctxt "@label link to Connect and Cloud interfaces"
+msgid "Manage printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:254
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:192
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:183
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:256
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:514
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:248
msgctxt "@info"
-msgid ""
-"These options are not available because you are monitoring a cloud printer."
+msgid "Please update your printer's firmware to manage the queue remotely."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:289
msgctxt "@info"
msgid "The webcam is not available because you are monitoring a cloud printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:301
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:348
msgctxt "@label:status"
msgid "Loading..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:305
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:352
msgctxt "@label:status"
msgid "Unavailable"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:309
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:356
msgctxt "@label:status"
msgid "Unreachable"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:360
msgctxt "@label:status"
msgid "Idle"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
msgctxt "@label"
msgid "Untitled"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:373
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:422
msgctxt "@label"
msgid "Anonymous"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:399
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:449
msgctxt "@label:status"
msgid "Requires configuration changes"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:436
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:487
msgctxt "@action:button"
msgid "Details"
msgstr ""
@@ -2118,12 +1964,6 @@ msgctxt "@label"
msgid "First available"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:187
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:132
-msgctxt "@label"
-msgid "Glass"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
msgctxt "@label"
msgid "Queued"
@@ -2131,201 +1971,200 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
msgctxt "@label link to connect manager"
-msgid "Go to Cura Connect"
+msgid "Manage in browser"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:100
+msgctxt "@label"
+msgid "There are no print jobs in the queue. Slice and send a job to add one."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:115
msgctxt "@label"
msgid "Print jobs"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:131
msgctxt "@label"
msgid "Total print time"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:130
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:147
msgctxt "@label"
msgid "Waiting for"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:246
-msgctxt "@label link to connect manager"
-msgid "View print history"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:46
-msgctxt "@window:title"
-msgid "Existing Connection"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:48
-msgctxt "@message:text"
-msgid ""
-"This printer/group is already added to Cura. Please select another printer/"
-"group."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:65
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
msgctxt "@label"
msgid ""
"To print directly to your printer over the network, please make sure your "
"printer is connected to the network using a network cable or by connecting "
"your printer to your WIFI network. If you don't connect Cura with your "
"printer, you can still use a USB drive to transfer g-code files to your "
-"printer.\n"
-"\n"
-"Select your printer from the list below:"
+"printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
-msgctxt "@action:button"
-msgid "Add"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
+msgctxt "@label"
+msgid "Select your printer from the list below:"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:97
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
msgctxt "@action:button"
msgid "Edit"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:108
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:138
msgctxt "@action:button"
msgid "Remove"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:96
msgctxt "@action:button"
msgid "Refresh"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:211
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:176
msgctxt "@label"
msgid ""
"If your printer is not listed, read the network printing "
"troubleshooting guide"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:240
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:258
msgctxt "@label"
msgid "Type"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:279
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:274
msgctxt "@label"
msgid "Firmware version"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:290
msgctxt "@label"
msgid "Address"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:317
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:263
msgctxt "@label"
msgid "This printer is not set up to host a group of printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:267
msgctxt "@label"
msgid "This printer is the host for a group of %1 printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:332
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:278
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:337
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
msgctxt "@action:button"
msgid "Connect"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:351
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:296
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:146
+msgctxt "@text"
+msgid "Please enter a valid IP address."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:308
msgctxt "@title:window"
msgid "Printer Address"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:374
-msgctxt "@alabel"
-msgid "Enter the IP address or hostname of your printer on the network."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
+msgid "Enter the IP address of your printer on the network."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:404
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:361
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:138
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
msgctxt "@label:status"
msgid "Aborted"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:80
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:82
msgctxt "@label:status"
msgid "Finished"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:86
msgctxt "@label:status"
msgid "Preparing..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
msgctxt "@label:status"
msgid "Aborting..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
msgctxt "@label:status"
msgid "Pausing..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:104
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
msgctxt "@label:status"
msgid "Paused"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
msgctxt "@label:status"
msgid "Resuming..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:108
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
msgctxt "@label:status"
msgid "Action required"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:110
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
msgctxt "@label:status"
msgid "Finishes %1 at %2"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:44
-msgctxt "@action:button"
-msgid "Print"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:11
msgctxt "@title:window"
msgid "Print over network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:52
+msgctxt "@action:button"
+msgid "Print"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:80
msgctxt "@label"
msgid "Printer selection"
msgstr ""
@@ -2414,7 +2253,7 @@ msgctxt "@action:button"
msgid "Override"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:64
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:85
msgctxt "@label"
msgid "The assigned printer, %1, requires the following configuration change:"
msgid_plural ""
@@ -2422,151 +2261,142 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:68
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:89
msgctxt "@label"
msgid ""
"The printer %1 is assigned, but the job contains an unknown material "
"configuration."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:99
msgctxt "@label"
msgid "Change material %1 from %2 to %3."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:102
msgctxt "@label"
msgid "Load %3 as material %1 (This cannot be overridden)."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:105
msgctxt "@label"
msgid "Change print core %1 from %2 to %3."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:108
msgctxt "@label"
msgid "Change build plate to %1 (This cannot be overridden)."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:94
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:115
msgctxt "@label"
msgid ""
"Override will use the specified settings with the existing printer "
"configuration. This may result in a failed print."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:135
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:156
msgctxt "@label"
msgid "Aluminum"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:75
-msgctxt "@info:tooltip"
-msgid "Connect to a printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:92
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:100
msgctxt "@info"
msgid ""
"Please make sure your printer has a connection:\n"
"- Check if the printer is turned on.\n"
-"- Check if the printer is connected to the network."
+"- Check if the printer is connected to the network.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:110
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
msgctxt "@info"
-msgid "Please select a network connected printer to monitor."
+msgid "Please connect your printer to the network."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:126
-msgctxt "@info"
-msgid "Please connect your Ultimaker printer to your local network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:165
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
msgctxt "@label link to technical assistance"
msgid "View user manuals online"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:18
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:47
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:105
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:109
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:113
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:117
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:154
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:229
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
msgid "Travels"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:235
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
msgid "Helpers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:241
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
msgid "Shell"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:247
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
msgid "Infill"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:307
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:308
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:325
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:432
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr ""
@@ -2596,31 +2426,26 @@ msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:16
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:17
msgctxt "@title:window"
msgid "More information on anonymous data collection"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:66
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:74
msgctxt "@text:window"
msgid ""
-"Cura sends anonymous data to Ultimaker in order to improve the print quality "
-"and user experience. Below is an example of all the data that is sent."
+"Ultimaker Cura collects anonymous data in order to improve the print quality "
+"and user experience. Below is an example of all the data that is shared:"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:101
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:109
msgctxt "@text:window"
-msgid "I don't want to send this data"
+msgid "I don't want to send anonymous data"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:111
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:118
msgctxt "@text:window"
-msgid "Allow sending this data to Ultimaker and help us improve Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/R2D2/EvaluationSidebar.qml:49
-msgctxt "@label"
-msgid "No print selected"
+msgid "Allow sending anonymous data"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
@@ -2671,15 +2496,10 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:126
msgctxt "@info:tooltip"
msgid ""
-"By default, white pixels represent high points on the mesh and black pixels "
-"represent low points on the mesh. Change this option to reverse the behavior "
-"such that black pixels represent high points on the mesh and white pixels "
-"represent low points on the mesh."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
-msgctxt "@item:inlistbox"
-msgid "Lighter is higher"
+"For lithophanes dark pixels should correspond to thicker locations in order "
+"to block more light coming through. For height maps lighter pixels signify "
+"higher terrain, so lighter pixels should correspond to thicker locations in "
+"the generated 3D model."
msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
@@ -2687,6 +2507,11 @@ msgctxt "@item:inlistbox"
msgid "Darker is higher"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
+msgctxt "@item:inlistbox"
+msgid "Lighter is higher"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:149
msgctxt "@info:tooltip"
msgid "The amount of smoothing to apply to the image."
@@ -2697,70 +2522,69 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:37
-msgctxt "@label"
-msgid "Mesh Type"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:68
-msgctxt "@label"
-msgid "Normal model"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:75
-msgctxt "@label"
-msgid "Print as support"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:83
-msgctxt "@label"
-msgid "Don't support overlap with other models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:91
-msgctxt "@label"
-msgid "Modify settings for overlap with other models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:99
-msgctxt "@label"
-msgid "Modify settings for infill of other models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
-msgctxt "@action:button"
-msgid "Select settings"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:13
msgctxt "@title:window"
msgid "Select Settings to Customize for this model"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:431
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:56
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:445
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:70
msgctxt "@label:checkbox"
msgid "Show all"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:44
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:85
+msgctxt "@label"
+msgid "Normal model"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:97
+msgctxt "@label"
+msgid "Print as support"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:109
+msgctxt "@label"
+msgid "Modify settings for overlaps"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:121
+msgctxt "@label"
+msgid "Don't support overlaps"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:145
+msgctxt "@action:checkbox"
+msgid "Infill only"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:368
+msgctxt "@action:button"
+msgid "Select settings"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:14
msgctxt "@title:window"
msgid "Open Project"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:58
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Update/override existing profile"
msgid "Update existing"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:59
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Save settings in a new profile"
msgid "Create new"
msgstr ""
@@ -2787,6 +2611,11 @@ msgctxt "@action:ComboBox option"
msgid "Update"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
+msgctxt "@action:ComboBox option"
+msgid "Create new"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
@@ -2800,7 +2629,7 @@ msgid "Printer Group"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:220
msgctxt "@action:label"
msgid "Profile settings"
msgstr ""
@@ -2811,75 +2640,81 @@ msgid "How should the conflict in the profile be resolved?"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:323
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:221
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:244
msgctxt "@action:label"
msgid "Name"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:261
+msgctxt "@action:label"
+msgid "Intent"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:228
msgctxt "@action:label"
msgid "Not in profile"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:210
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:233
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:247
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:262
msgctxt "@action:label"
msgid "Derivative from"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:252
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:267
msgctxt "@action:label"
msgid "%1, %2 override"
msgid_plural "%1, %2 overrides"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:268
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:283
msgctxt "@action:label"
msgid "Material settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:284
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:299
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:342
msgctxt "@action:label"
msgid "Setting visibility"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:336
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:351
msgctxt "@action:label"
msgid "Mode"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:367
msgctxt "@action:label"
msgid "Visible settings:"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:372
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:383
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:398
msgctxt "@action:warning"
msgid "Loading a project will clear all models on the build plate."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:401
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:416
msgctxt "@action:button"
msgid "Open"
msgstr ""
@@ -2910,6 +2745,7 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:51
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:138
msgctxt "@button"
msgid "Sign in"
msgstr ""
@@ -2991,65 +2827,12 @@ msgctxt "@checkbox:description"
msgid "Automatically create a backup each day that Cura is started."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMainSettingsSelector.qml:75
-msgctxt "@label"
-msgid "Not supported"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:35
-msgctxt "@action:button"
-msgid "Previous"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
-msgctxt "@action:button"
-msgid "Export"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
-msgctxt "@action:button"
-msgid "Next"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:169
-msgctxt "@label"
-msgid "Tip"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:160
-msgctxt "@label"
-msgid "Print experiment"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageValidation.qml:25
-msgctxt "@label"
-msgid "Checklist"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:26
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:25
-msgctxt "@title"
-msgid "Select Printer Upgrades"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:38
-msgctxt "@label"
-msgid "Please select any upgrades made to this Ultimaker 2."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
-msgctxt "@label"
-msgid "Olsson Block"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:30
msgctxt "@title"
msgid "Build Plate Leveling"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:38
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:44
msgctxt "@label"
msgid ""
"To make sure your prints will come out great, you can now adjust your "
@@ -3057,7 +2840,7 @@ msgid ""
"the different positions that can be adjusted."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:57
msgctxt "@label"
msgid ""
"For every position; insert a piece of paper under the nozzle and adjust the "
@@ -3065,121 +2848,26 @@ msgid ""
"paper is slightly gripped by the tip of the nozzle."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:62
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:75
msgctxt "@action:button"
msgid "Start Build Plate Leveling"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:74
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:87
msgctxt "@action:button"
msgid "Move to Next Position"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:37
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker Original"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:45
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:41
msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
-msgctxt "@title"
-msgid "Check Printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
-msgctxt "@label"
-msgid ""
-"It's a good idea to do a few sanity checks on your Ultimaker. You can skip "
-"this step if you know your machine is functional"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
-msgctxt "@action:button"
-msgid "Start Printer Check"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
-msgctxt "@label"
-msgid "Connection: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Connected"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Not connected"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
-msgctxt "@label"
-msgid "Min endstop X: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-msgctxt "@info:status"
-msgid "Works"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Not checked"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
-msgctxt "@label"
-msgid "Min endstop Y: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
-msgctxt "@label"
-msgid "Min endstop Z: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
-msgctxt "@label"
-msgid "Nozzle temperature check: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Stop Heating"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Start Heating"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
-msgctxt "@label"
-msgid "Build plate temperature check:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Checked"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
-msgctxt "@label"
-msgid "Everything is in order! You're done with your CheckUp."
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
@@ -3230,174 +2918,180 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
msgctxt "@title"
msgid "Information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
msgctxt "@title:window"
msgid "Confirm Diameter Change"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:102
msgctxt "@label (%1 is a number)"
msgid ""
"The new filament diameter is set to %1 mm, which is not compatible with the "
"current extruder. Do you wish to continue?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:128
msgctxt "@label"
msgid "Display Name"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:138
msgctxt "@label"
msgid "Brand"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:148
msgctxt "@label"
msgid "Material Type"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:158
msgctxt "@label"
msgid "Color"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:208
msgctxt "@label"
msgid "Properties"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:214
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:210
msgctxt "@label"
msgid "Density"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:229
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:225
msgctxt "@label"
msgid "Diameter"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:259
msgctxt "@label"
msgid "Filament Cost"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:276
msgctxt "@label"
msgid "Filament weight"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:294
msgctxt "@label"
msgid "Filament length"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:307
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:303
msgctxt "@label"
msgid "Cost per Meter"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:317
msgctxt "@label"
msgid "This material is linked to %1 and shares some of its properties."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:324
msgctxt "@label"
msgid "Unlink Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:339
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:335
msgctxt "@label"
msgid "Description"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:352
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:348
msgctxt "@label"
msgid "Adhesion Information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:17
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
msgctxt "@label"
msgid "Print settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:84
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:84
msgctxt "@action:button"
msgid "Activate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:126
msgctxt "@action:button"
msgid "Create"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:140
msgctxt "@action:button"
msgid "Duplicate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:141
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:167
msgctxt "@action:button"
msgid "Import"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:203
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:179
+msgctxt "@action:button"
+msgid "Export"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:233
msgctxt "@action:label"
msgid "Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:262
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:274
msgctxt "@title:window"
msgid "Confirm Remove"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:263
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:247
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:300
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:275
msgctxt "@label (%1 is object name)"
msgid "Are you sure you wish to remove %1? This cannot be undone!"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:277
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:285
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:322
msgctxt "@title:window"
msgid "Import Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:323
msgctxt "@info:status Don't translate the XML tags or !"
msgid ""
"Could not import material %1: %2"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:327
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully imported material %1"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:316
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:345
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:353
msgctxt "@title:window"
msgid "Export Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:357
msgctxt "@info:status Don't translate the XML tags and !"
msgid ""
"Failed to export material to %1: %2"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:363
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr ""
@@ -3412,248 +3106,282 @@ msgctxt "@label:textbox"
msgid "Check all"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:47
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:61
msgctxt "@info:status"
msgid "Calculated"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:75
msgctxt "@title:column"
msgid "Setting"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
msgctxt "@title:column"
msgid "Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:74
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:89
msgctxt "@title:column"
msgid "Current"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:97
msgctxt "@title:column"
msgid "Unit"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:126
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:132
msgctxt "@label"
msgid "Interface"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:143
msgctxt "@label"
msgid "Language:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:210
msgctxt "@label"
msgid "Currency:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:223
msgctxt "@label"
msgid "Theme:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:273
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:279
msgctxt "@label"
msgid ""
"You will need to restart the application for these changes to have effect."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:296
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
msgctxt "@option:check"
msgid "Slice automatically"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:312
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
msgctxt "@label"
msgid "Viewport behavior"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
msgctxt "@info:tooltip"
msgid ""
"Highlight unsupported areas of the model in red. Without support these areas "
"will not print properly."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:335
msgctxt "@option:check"
msgid "Display overhang"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:343
msgctxt "@info:tooltip"
msgid ""
"Moves the camera so the model is in the center of the view when a model is "
"selected"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:348
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:355
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
+msgctxt "@info:tooltip"
+msgid ""
+"Zooming towards the mouse is not supported in the orthographic perspective."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:380
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:410
msgctxt "@info:tooltip"
msgid ""
"Should models on the platform be moved so that they no longer intersect?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:385
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:394
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:424
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved down to touch the build plate?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:429
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:411
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:428
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:458
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:463
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
+msgctxt "@info:tooltip"
+msgid "Should Cura open at the location it was closed?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
+msgctxt "@option:check"
+msgid "Restore window position on start"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:488
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:495
+msgctxt "@window:text"
+msgid "Camera rendering:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+msgid "Perspective"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+msgid "Orthographic"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
msgctxt "@label"
msgid "Opening and saving files"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:456
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:545
msgctxt "@info:tooltip"
msgid "Should models be scaled to the build volume if they are too large?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:461
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:550
msgctxt "@option:check"
msgid "Scale large models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:560
msgctxt "@info:tooltip"
msgid ""
"An model may appear extremely small if its unit is for example in meters "
"rather than millimeters. Should these models be scaled up?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:565
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:491
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:580
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
msgctxt "@info:tooltip"
msgid ""
"Should a prefix based on the printer name be added to the print job name "
"automatically?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:516
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:605
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:609
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:627
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:642
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:554
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:openProject"
msgid "Always import models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:679
msgctxt "@info:tooltip"
msgid ""
"When you have made changes to a profile and switched to a different one, a "
@@ -3661,50 +3389,51 @@ msgid ""
"not, or you can choose a default behaviour and never show that dialog again."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:599
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:52
msgctxt "@label"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:693
msgctxt "@window:text"
msgid ""
"Default behavior for changed setting values when switching to a different "
"profile: "
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:707
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:157
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:709
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:654
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
msgctxt "@label"
msgid "Privacy"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:661
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:750
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:666
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:755
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:676
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:765
msgctxt "@info:tooltip"
msgid ""
"Should anonymous data about your print be sent to Ultimaker? Note, no "
@@ -3712,132 +3441,108 @@ msgid ""
"stored."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:681
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:770
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:690
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:779
msgctxt "@action:button"
msgid "More information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
-msgctxt "@label"
-msgid "Experimental"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:715
-msgctxt "@info:tooltip"
-msgid "Use multi build plate functionality"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
-msgctxt "@option:check"
-msgid "Use multi build plate functionality (restart required)"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:16
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:57
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:63
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
msgctxt "@action:button"
msgid "Rename"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:363
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:419
msgctxt "@title:tab"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:104
msgctxt "@label"
msgid "Create"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@label"
msgid "Duplicate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:202
msgctxt "@title:window"
msgid "Create Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:176
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:204
msgctxt "@info"
msgid "Please provide a name for this profile."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:260
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:291
msgctxt "@title:window"
msgid "Rename Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:276
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:304
msgctxt "@title:window"
msgid "Import Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:333
msgctxt "@title:window"
msgid "Export Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:396
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Default profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Custom profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:554
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:561
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:257
msgctxt "@action:button"
msgid "Discard current changes"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:514
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:580
msgctxt "@action:label"
msgid ""
"This profile uses the defaults specified by the printer, so it has no "
"settings/overrides in the list below."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:521
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:588
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:606
msgctxt "@title:tab"
msgid "Global Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:90
msgctxt "@action:button"
msgid "Marketplace"
msgstr ""
@@ -3880,12 +3585,12 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
msgctxt "@title:window"
msgid "New project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:125
msgctxt "@info:question"
msgid ""
"Are you sure you want to start a new project? This will clear the build "
@@ -3899,36 +3604,36 @@ msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "search settings"
+msgid "Search settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:462
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:474
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:471
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:521
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:557
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr ""
@@ -3942,29 +3647,36 @@ msgid ""
"Click to make these settings visible."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:81
+msgctxt "@label"
+msgid ""
+"This setting is not used because all the settings that it influences are "
+"overridden."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:86
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:91
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:166
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:187
msgctxt "@label"
msgid ""
"This setting is always shared between all extruders. Changing it here will "
"change the value for all extruders."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:191
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:230
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3972,7 +3684,7 @@ msgid ""
"Click to restore the value of the profile."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:329
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value "
@@ -3981,12 +3693,25 @@ msgid ""
"Click to restore the calculated value."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/NoIntentIcon.qml:31
+msgctxt ""
+"@label %1 is filled in with the type of a profile. %2 is filled with a list "
+"of numbers (eg '1' or '1, 2')"
+msgid ""
+"There is no %1 profile for the configuration in extruder %2. The default "
+"intent will be used instead"
+msgid_plural ""
+"There is no %1 profile for the configurations in extruders %2. The default "
+"intent will be used instead"
+msgstr[0] ""
+msgstr[1] ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
msgctxt "@button"
msgid "Recommended"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
msgctxt "@button"
msgid "Custom"
msgstr ""
@@ -4002,64 +3727,37 @@ msgid ""
"Gradual infill will gradually increase the amount of infill towards the top."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:29
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:30
msgctxt "@label"
msgid "Support"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:71
msgctxt "@label"
msgid ""
"Generate structures to support parts of the model which have overhangs. "
"Without these structures, such parts would collapse during printing."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:136
-msgctxt "@label"
-msgid ""
-"Select which extruder to use for support. This will build up supporting "
-"structures below the model to prevent the model from sagging or printing in "
-"mid air."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:29
msgctxt "@label"
msgid "Adhesion"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:74
msgctxt "@label"
msgid ""
"Enable printing a brim or raft. This will add a flat area around or under "
"your object which is easy to cut off afterwards."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:175
-msgctxt "@label"
-msgid "Layer Height"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:206
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:81
msgctxt "@tooltip"
msgid ""
"You have modified some profile settings. If you want to change these go to "
"custom mode."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:355
-msgctxt "@tooltip"
-msgid ""
-"This quality profile is not available for your current material and nozzle "
-"configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:449
-msgctxt "@tooltip"
-msgid ""
-"A custom profile is currently active. To enable the quality slider, choose a "
-"default quality profile in Custom tab"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:13
msgctxt "@label:Should be short"
msgid "On"
@@ -4070,12 +3768,17 @@ msgctxt "@label:Should be short"
msgid "Off"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:33
+msgctxt "@label"
+msgid "Experimental"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:47
msgctxt "@label"
msgid "Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:172
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the "
@@ -4084,9 +3787,14 @@ msgid ""
"Click to open the profile manager."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:160
+msgctxt "@label:header"
+msgid "Custom profiles"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:21
msgctxt "@label shown when we load a Gcode file"
-msgid "Print setup disabled. G code file can not be modified."
+msgid "Print setup disabled. G-code file can not be modified."
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
@@ -4119,48 +3827,48 @@ msgctxt "@label"
msgid "Send G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:364
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:365
msgctxt "@tooltip of G-code command input"
msgid ""
"Send a custom G-code command to the connected printer. Press 'enter' to send "
"the command."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:41
msgctxt "@label"
msgid "Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:71
msgctxt "@tooltip"
msgid ""
"The target temperature of the hotend. The hotend will heat up or cool down "
"towards this temperature. If this is 0, the hotend heating is turned off."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:103
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:177
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:332
msgctxt "@button Cancel pre-heating"
msgid "Cancel"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:344
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:335
msgctxt "@button"
msgid "Pre-heat"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:370
msgctxt "@tooltip of pre-heat"
msgid ""
"Heat the hotend in advance before printing. You can continue adjusting your "
@@ -4168,17 +3876,17 @@ msgid ""
"up when you're ready to print."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:406
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:438
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:470
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr ""
@@ -4223,12 +3931,12 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:46
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:71
msgctxt "@label:category menu label"
msgid "Generic"
msgstr ""
@@ -4248,42 +3956,47 @@ msgctxt "@title:menu menubar:settings"
msgid "&Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:26
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:27
msgctxt "@title:menu"
msgid "&Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:36
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Enable Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:49
msgctxt "@action:inmenu"
msgid "Disable Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:62
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:65
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:19
msgctxt "@action:inmenu menubar:view"
msgid "&Camera position"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:44
+msgctxt "@action:inmenu menubar:view"
+msgid "Camera view"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:47
+msgctxt "@action:inmenu menubar:view"
+msgid "Perspective"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:59
+msgctxt "@action:inmenu menubar:view"
+msgid "Orthographic"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:80
msgctxt "@action:inmenu menubar:view"
msgid "&Build plate"
msgstr ""
@@ -4303,17 +4016,17 @@ msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:33
msgctxt "@title:menu menubar:file"
msgid "&Save..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:54
msgctxt "@title:menu menubar:file"
msgid "&Export..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:65
msgctxt "@action:inmenu menubar:file"
msgid "Export Selection..."
msgstr ""
@@ -4342,17 +4055,12 @@ msgctxt "@header"
msgid "Configurations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:112
msgctxt "@label"
msgid "Select configuration"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:201
-msgctxt "@label"
-msgid "See the material compatibility chart"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:274
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:223
msgctxt "@label"
msgid "Configurations"
msgstr ""
@@ -4378,17 +4086,17 @@ msgctxt "@label"
msgid "Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:202
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
msgctxt "@label"
msgid "Enabled"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:251
msgctxt "@label"
msgid "Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:344
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:378
msgctxt "@label"
msgid "Use glue for better adhesion with this material combination."
msgstr ""
@@ -4410,42 +4118,47 @@ msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:169
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
msgctxt "@label"
-msgid "View types"
+msgid "View type"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
msgctxt "@label"
-msgid "Hi "
+msgid "Object list"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:22
+msgctxt "@label The argument is a username."
+msgid "Hi %1"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:33
msgctxt "@button"
msgid "Ultimaker account"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
msgctxt "@button"
msgid "Sign out"
msgstr ""
@@ -4455,11 +4168,6 @@ msgctxt "@action:button"
msgid "Sign in"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:29
-msgctxt "@label"
-msgid "Ultimaker Cloud"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
msgctxt "@label"
msgid "The next generation 3D printing workflow"
@@ -4470,7 +4178,7 @@ msgctxt "@text"
msgid ""
"- Send print jobs to Ultimaker printers outside your local network\n"
"- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
-"- Get exclusive access to material profiles from leading brands"
+"- Get exclusive access to print profiles from leading brands"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
@@ -4483,49 +4191,54 @@ msgctxt "@label"
msgid "No time estimation available"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:76
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
msgctxt "@label"
msgid "No cost estimation available"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
msgctxt "@button"
msgid "Preview"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:55
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:61
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:67
msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
+msgid "Unable to slice"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:116
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
+msgctxt "@button"
+msgid "Processing"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
msgctxt "@button"
msgid "Slice"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
msgctxt "@label"
msgid "Start the slicing process"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
msgctxt "@button"
msgid "Cancel"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
msgctxt "@label"
-msgid "Time specification"
+msgid "Time estimation"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
msgctxt "@label"
-msgid "Material specification"
+msgid "Material estimation"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
@@ -4548,275 +4261,285 @@ msgctxt "@label"
msgid "Preset printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
msgctxt "@button"
msgid "Add printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:173
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
msgctxt "@button"
msgid "Manage printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
msgctxt "@action:inmenu"
msgid "Show Online Troubleshooting Guide"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
+msgctxt "@action:inmenu"
+msgid "Exit Full Screen"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:103
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:113
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:123
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:131
msgctxt "@action:inmenu menubar:view"
msgid "3D View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:138
msgctxt "@action:inmenu menubar:view"
msgid "Front View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:145
msgctxt "@action:inmenu menubar:view"
msgid "Top View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:152
msgctxt "@action:inmenu menubar:view"
msgid "Left Side View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:159
msgctxt "@action:inmenu menubar:view"
msgid "Right Side View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:173
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:179
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195
msgctxt "@action:inmenu menubar:profile"
msgid "&Update profile with current settings/overrides"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:192
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:229
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:237
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:245
+msgctxt "@action:inmenu menubar:help"
+msgid "What's New"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
msgctxt "@action:inmenu menubar:help"
msgid "About..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:258
msgctxt "@action:inmenu menubar:edit"
msgid "Delete Selected Model"
msgid_plural "Delete Selected Models"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
msgctxt "@action:inmenu menubar:edit"
msgid "Center Selected Model"
msgid_plural "Center Selected Models"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
msgctxt "@action:inmenu menubar:edit"
msgid "Multiply Selected Model"
msgid_plural "Multiply Selected Models"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:294
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:283
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:300
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:303
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:320
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:313
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:347
msgctxt "@action:inmenu menubar:edit"
msgid "Select All Models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:357
msgctxt "@action:inmenu menubar:edit"
msgid "Clear Build Plate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:367
msgctxt "@action:inmenu menubar:file"
msgid "Reload All Models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:376
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models To All Build Plates"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:383
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:391
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:381
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:398
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:405
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Transformations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:412
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:420
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:427
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
msgid "&Marketplace"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:181
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
msgctxt "@label"
msgid "This package will be installed after restarting."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:538
msgctxt "@title:window"
msgid "Closing Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:487
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:499
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:551
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:589
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:19
msgctxt "@title:window"
msgid "Open file(s)"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:632
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:695
msgctxt "@window:title"
msgid "Install Package"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:640
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:703
msgctxt "@title:window"
msgid "Open File(s)"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:643
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:706
msgctxt "@text:window"
msgid ""
"We have found one or more G-Code files within the files you have selected. "
@@ -4824,12 +4547,16 @@ msgid ""
"file, please just select only one."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:713
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:18
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:809
msgctxt "@title:window"
msgid "Add Printer"
msgstr ""
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:817
+msgctxt "@title:window"
+msgid "What's New"
+msgstr ""
+
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
msgctxt "@label %1 is filled in with the name of an extruder"
msgid "Print Selected Model with %1"
@@ -4889,174 +4616,144 @@ msgctxt "@action:button"
msgid "Create New Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:78
-msgctxt "@title:tab"
-msgid "Add a printer to Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:92
-msgctxt "@title:tab"
-msgid ""
-"Select the printer you want to use from the list below.\n"
-"\n"
-"If your printer is not in the list, use the \"Custom FFF Printer\" from the "
-"\"Custom\" category and adjust the settings to match your printer in the "
-"next dialog."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:249
-msgctxt "@label"
-msgid "Manufacturer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:271
-msgctxt "@label"
-msgid "Printer Name"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:294
-msgctxt "@action:button"
-msgid "Add Printer"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:15
msgctxt "@title:window"
msgid "About Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:56
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:57
msgctxt "@label"
msgid "version: %1"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:72
msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:85
msgctxt "@info:credit"
msgid ""
"Cura is developed by Ultimaker B.V. in cooperation with the community.\n"
"Cura proudly uses the following open source projects:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
msgctxt "@label"
msgid "Graphical user interface"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
msgctxt "@label"
msgid "Application framework"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
msgctxt "@label"
msgid "G-code generator"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:138
msgctxt "@label"
msgid "Interprocess communication library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
msgctxt "@label"
msgid "Programming language"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
msgctxt "@label"
msgid "GUI framework"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
msgctxt "@label"
msgid "GUI framework bindings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
msgctxt "@label"
msgid "C/C++ Binding library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
msgctxt "@label"
msgid "Data interchange format"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
msgctxt "@label"
msgid "Support library for scientific computing"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
msgctxt "@label"
msgid "Support library for faster math"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
msgctxt "@label"
msgid "Support library for handling STL files"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
msgctxt "@label"
msgid "Support library for handling planar objects"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
msgctxt "@label"
msgid "Support library for handling triangular meshes"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
msgctxt "@label"
msgid "Support library for analysis of complex networks"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
msgctxt "@label"
msgid "Support library for handling 3MF files"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
msgctxt "@label"
msgid "Support library for file metadata and streaming"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
msgctxt "@label"
msgid "Serial communication library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
msgctxt "@label"
msgid "ZeroConf discovery library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
msgctxt "@label"
msgid "Polygon clipping library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:156
msgctxt "@Label"
msgid "Python HTTP library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
msgctxt "@label"
msgid "Font"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
msgctxt "@label"
msgid "SVG icons"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:160
msgctxt "@label"
msgid "Linux cross-distribution application deployment"
msgstr ""
@@ -5079,27 +4776,27 @@ msgctxt "@title:window"
msgid "Save Project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:138
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:177
msgctxt "@action:label"
msgid "Extruder %1"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:192
msgctxt "@action:label"
msgid "%1 & material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:243
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:194
+msgctxt "@action:label"
+msgid "Material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:label"
msgid "Don't show project summary on save again"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:262
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:302
msgctxt "@action:button"
msgid "Save"
msgstr ""
@@ -5131,28 +4828,768 @@ msgctxt "@action:button"
msgid "Import models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:210
-msgctxt "@option:check"
-msgid "See only current build plate"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
+msgctxt "@label"
+msgid "Empty"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:226
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
+msgctxt "@label"
+msgid "Add a printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:246
-msgctxt "@action:button"
-msgid "Arrange current build plate"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
+msgctxt "@label"
+msgid "Add a networked printer"
msgstr ""
-#: X3GWriter/plugin.json
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
+msgctxt "@label"
+msgid "Add a non-networked printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:70
+msgctxt "@label"
+msgid "Add printer by IP address"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:133
+msgctxt "@text"
+msgid "Place enter your printer's IP address."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:204
+msgctxt "@label"
+msgid "Could not connect to device."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:208
+msgctxt "@label"
+msgid "The printer at this address has not responded yet."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:240
+msgctxt "@label"
+msgid ""
+"This printer cannot be added because it's an unknown printer or it's not the "
+"host of a group."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:329
+msgctxt "@button"
+msgid "Back"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:342
+msgctxt "@button"
+msgid "Connect"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/FirstStartMachineActionsContent.qml:77
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:123
+msgctxt "@button"
+msgid "Next"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:23
+msgctxt "@label"
+msgid "User Agreement"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:56
+msgctxt "@button"
+msgid "Agree"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:70
+msgctxt "@button"
+msgid "Decline and close"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:24
+msgctxt "@label"
+msgid "Help us to improve Ultimaker Cura"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:57
+msgctxt "@text"
+msgid ""
+"Ultimaker Cura collects anonymous data to improve print quality and user "
+"experience, including:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:71
+msgctxt "@text"
+msgid "Machine types"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:77
+msgctxt "@text"
+msgid "Material usage"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:83
+msgctxt "@text"
+msgid "Number of slices"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:89
+msgctxt "@text"
+msgid "Print settings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:102
+msgctxt "@text"
+msgid ""
+"Data collected by Ultimaker Cura will not contain any personal information."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:103
+msgctxt "@text"
+msgid "More information"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WhatsNewContent.qml:24
+msgctxt "@label"
+msgid "What's new in Ultimaker Cura"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:42
+msgctxt "@label"
+msgid "There is no printer found over your network."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:179
+msgctxt "@label"
+msgid "Refresh"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:190
+msgctxt "@label"
+msgid "Add printer by IP"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:223
+msgctxt "@label"
+msgid "Troubleshooting"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:211
+msgctxt "@label"
+msgid "Printer name"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:224
+msgctxt "@text"
+msgid "Please give your printer a name"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:36
+msgctxt "@label"
+msgid "Ultimaker Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:77
+msgctxt "@text"
+msgid "The next generation 3D printing workflow"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:94
+msgctxt "@text"
+msgid "- Send print jobs to Ultimaker printers outside your local network"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:97
+msgctxt "@text"
+msgid "- Store your Ultimaker Cura settings in the cloud for use anywhere"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:100
+msgctxt "@text"
+msgid "- Get exclusive access to print profiles from leading brands"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:119
+msgctxt "@button"
+msgid "Finish"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:128
+msgctxt "@button"
+msgid "Create an account"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:29
+msgctxt "@label"
+msgid "Welcome to Ultimaker Cura"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:47
+msgctxt "@text"
+msgid ""
+"Please follow these steps to set up\n"
+"Ultimaker Cura. This will only take a few moments."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:58
+msgctxt "@button"
+msgid "Get started"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:27
+msgctxt "@info:tooltip"
+msgid "3D View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:40
+msgctxt "@info:tooltip"
+msgid "Front View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
+msgctxt "@info:tooltip"
+msgid "Top View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
+msgctxt "@info:tooltip"
+msgid "Left View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:79
+msgctxt "@info:tooltip"
+msgid "Right View"
+msgstr ""
+
+#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
+msgid ""
+"Provides a way to change machine settings (such as build volume, nozzle "
+"size, etc.)."
msgstr ""
-#: X3GWriter/plugin.json
+#: MachineSettingsAction/plugin.json
msgctxt "name"
-msgid "X3GWriter"
+msgid "Machine Settings action"
msgstr ""
+#: Toolbox/plugin.json
+msgctxt "description"
+msgid "Find, manage and install new Cura packages."
+msgstr ""
+
+#: Toolbox/plugin.json
+msgctxt "name"
+msgid "Toolbox"
+msgstr ""
+
+#: XRayView/plugin.json
+msgctxt "description"
+msgid "Provides the X-Ray view."
+msgstr ""
+
+#: XRayView/plugin.json
+msgctxt "name"
+msgid "X-Ray View"
+msgstr ""
+
+#: X3DReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading X3D files."
+msgstr ""
+
+#: X3DReader/plugin.json
+msgctxt "name"
+msgid "X3D Reader"
+msgstr ""
+
+#: GCodeWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a file."
+msgstr ""
+
+#: GCodeWriter/plugin.json
+msgctxt "name"
+msgid "G-code Writer"
+msgstr ""
+
+#: ModelChecker/plugin.json
+msgctxt "description"
+msgid ""
+"Checks models and print configuration for possible printing issues and give "
+"suggestions."
+msgstr ""
+
+#: ModelChecker/plugin.json
+msgctxt "name"
+msgid "Model Checker"
+msgstr ""
+
+#: FirmwareUpdater/plugin.json
+msgctxt "description"
+msgid "Provides a machine actions for updating firmware."
+msgstr ""
+
+#: FirmwareUpdater/plugin.json
+msgctxt "name"
+msgid "Firmware Updater"
+msgstr ""
+
+#: AMFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading AMF files."
+msgstr ""
+
+#: AMFReader/plugin.json
+msgctxt "name"
+msgid "AMF Reader"
+msgstr ""
+
+#: USBPrinting/plugin.json
+msgctxt "description"
+msgid ""
+"Accepts G-Code and sends them to a printer. Plugin can also update firmware."
+msgstr ""
+
+#: USBPrinting/plugin.json
+msgctxt "name"
+msgid "USB printing"
+msgstr ""
+
+#: GCodeGzWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a compressed archive."
+msgstr ""
+
+#: GCodeGzWriter/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Writer"
+msgstr ""
+
+#: UFPWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing Ultimaker Format Packages."
+msgstr ""
+
+#: UFPWriter/plugin.json
+msgctxt "name"
+msgid "UFP Writer"
+msgstr ""
+
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr ""
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr ""
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "description"
+msgid "Provides removable drive hotplugging and writing support."
+msgstr ""
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "name"
+msgid "Removable Drive Output Device Plugin"
+msgstr ""
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "description"
+msgid "Manages network connections to Ultimaker networked printers."
+msgstr ""
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "name"
+msgid "Ultimaker Network Connection"
+msgstr ""
+
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr ""
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr ""
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "description"
+msgid "Checks for firmware updates."
+msgstr ""
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "name"
+msgid "Firmware Update Checker"
+msgstr ""
+
+#: SimulationView/plugin.json
+msgctxt "description"
+msgid "Provides the Simulation view."
+msgstr ""
+
+#: SimulationView/plugin.json
+msgctxt "name"
+msgid "Simulation View"
+msgstr ""
+
+#: GCodeGzReader/plugin.json
+msgctxt "description"
+msgid "Reads g-code from a compressed archive."
+msgstr ""
+
+#: GCodeGzReader/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Reader"
+msgstr ""
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "description"
+msgid "Extension that allows for user created scripts for post processing"
+msgstr ""
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "name"
+msgid "Post Processing"
+msgstr ""
+
+#: SupportEraser/plugin.json
+msgctxt "description"
+msgid ""
+"Creates an eraser mesh to block the printing of support in certain places"
+msgstr ""
+
+#: SupportEraser/plugin.json
+msgctxt "name"
+msgid "Support Eraser"
+msgstr ""
+
+#: UFPReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading Ultimaker Format Packages."
+msgstr ""
+
+#: UFPReader/plugin.json
+msgctxt "name"
+msgid "UFP Reader"
+msgstr ""
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "description"
+msgid "Submits anonymous slice info. Can be disabled through preferences."
+msgstr ""
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "name"
+msgid "Slice info"
+msgstr ""
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "description"
+msgid "Provides capabilities to read and write XML-based material profiles."
+msgstr ""
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "name"
+msgid "Material Profiles"
+msgstr ""
+
+#: LegacyProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from legacy Cura versions."
+msgstr ""
+
+#: LegacyProfileReader/plugin.json
+msgctxt "name"
+msgid "Legacy Cura Profile Reader"
+msgstr ""
+
+#: GCodeProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from g-code files."
+msgstr ""
+
+#: GCodeProfileReader/plugin.json
+msgctxt "name"
+msgid "G-code Profile Reader"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.2 to 3.3"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.3 to 3.4"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.3 to Cura 4.4."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.3 to 4.4"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.5 to 2.6"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.7 to 3.0"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.5 to Cura 4.0."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.5 to 4.0"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.4 to 3.5"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.0 to Cura 4.1."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.0 to 4.1"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.0 to 3.1"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.1 to Cura 4.2."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.1 to 4.2"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.6 to 2.7"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.1 to 2.2"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.2 to 2.4"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.2 to Cura 4.3."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.2 to 4.3"
+msgstr ""
+
+#: ImageReader/plugin.json
+msgctxt "description"
+msgid "Enables ability to generate printable geometry from 2D image files."
+msgstr ""
+
+#: ImageReader/plugin.json
+msgctxt "name"
+msgid "Image Reader"
+msgstr ""
+
+#: TrimeshReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading model files."
+msgstr ""
+
+#: TrimeshReader/plugin.json
+msgctxt "name"
+msgid "Trimesh Reader"
+msgstr ""
+
+#: CuraEngineBackend/plugin.json
+msgctxt "description"
+msgid "Provides the link to the CuraEngine slicing backend."
+msgstr ""
+
+#: CuraEngineBackend/plugin.json
+msgctxt "name"
+msgid "CuraEngine Backend"
+msgstr ""
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "description"
+msgid "Provides the Per Model Settings."
+msgstr ""
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "name"
+msgid "Per Model Settings Tool"
+msgstr ""
+
+#: 3MFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading 3MF files."
+msgstr ""
+
+#: 3MFReader/plugin.json
+msgctxt "name"
+msgid "3MF Reader"
+msgstr ""
+
+#: SolidView/plugin.json
+msgctxt "description"
+msgid "Provides a normal solid mesh view."
+msgstr ""
+
+#: SolidView/plugin.json
+msgctxt "name"
+msgid "Solid View"
+msgstr ""
+
+#: GCodeReader/plugin.json
+msgctxt "description"
+msgid "Allows loading and displaying G-code files."
+msgstr ""
+
+#: GCodeReader/plugin.json
+msgctxt "name"
+msgid "G-code Reader"
+msgstr ""
+
+#: CuraDrive/plugin.json
+msgctxt "description"
+msgid "Backup and restore your configuration."
+msgstr ""
+
+#: CuraDrive/plugin.json
+msgctxt "name"
+msgid "Cura Backups"
+msgstr ""
+
+#: CuraProfileWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for exporting Cura profiles."
+msgstr ""
+
+#: CuraProfileWriter/plugin.json
+msgctxt "name"
+msgid "Cura Profile Writer"
+msgstr ""
+
+#: 3MFWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing 3MF files."
+msgstr ""
+
+#: 3MFWriter/plugin.json
+msgctxt "name"
+msgid "3MF Writer"
+msgstr ""
+
+#: PreviewStage/plugin.json
+msgctxt "description"
+msgid "Provides a preview stage in Cura."
+msgstr ""
+
+#: PreviewStage/plugin.json
+msgctxt "name"
+msgid "Preview Stage"
+msgstr ""
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "description"
+msgid ""
+"Provides machine actions for Ultimaker machines (such as bed leveling "
+"wizard, selecting upgrades, etc.)."
+msgstr ""
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "name"
+msgid "Ultimaker machine actions"
+msgstr ""
+
+#: CuraProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing Cura profiles."
+msgstr ""
+
+#: CuraProfileReader/plugin.json
+msgctxt "name"
+msgid "Cura Profile Reader"
+msgstr ""
diff --git a/resources/i18n/de_DE/cura.po b/resources/i18n/de_DE/cura.po
index 11acb189fd..3b0073bc31 100644
--- a/resources/i18n/de_DE/cura.po
+++ b/resources/i18n/de_DE/cura.po
@@ -5,20 +5,20 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
-"PO-Revision-Date: 2018-09-28 14:42+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: German\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: German , German \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.2.3\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr "Geräteeinstellungen"
@@ -40,13 +40,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr "G-Code-Datei"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr "GCodeWriter unterstützt keinen Nicht-Textmodus."
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr "Vor dem Exportieren bitte G-Code vorbereiten."
@@ -56,7 +56,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "3D-Modell-Assistent"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,71 +70,50 @@ msgstr ""
"
Erfahren Sie, wie Sie die bestmögliche Druckqualität und Zuverlässigkeit sicherstellen.
"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Changelog"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
-msgstr "Änderungsprotokoll anzeigen"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
msgctxt "@action"
msgid "Update Firmware"
msgstr "Firmware aktualisieren"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
-msgctxt "@item:inmenu"
-msgid "Flatten active settings"
-msgstr "Einstellungen Glätten aktiv"
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "AMF-Datei"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:35
-msgctxt "@info:status"
-msgid "Profile has been flattened & activated."
-msgstr "Das Profil wurde geglättet und aktiviert."
-
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:33
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "USB-Drucken"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:34
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:43
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Über USB drucken"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:35
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:44
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Über USB drucken"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:71
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:80
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Über USB verbunden"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:96
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:105
msgctxt "@label"
msgid "A USB print is in progress, closing Cura will stop this print. Are you sure?"
msgstr "Ein USB-Druck wird ausgeführt. Das Schließen von Cura beendet diesen Druck. Sind Sie sicher?"
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/install/X3GWriter/__init__.py:15
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
-msgctxt "X3G Writer File Description"
-msgid "X3G File"
-msgstr "X3G-Datei"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "A print is still in progress. Cura cannot start another print via USB until the previous print has completed."
+msgstr "Druck wird bearbeitet. Cura kann keinen weiteren Druck via USB starten, bis der vorherige Druck abgeschlossen wurde."
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
-msgctxt "X3g Writer Plugin Description"
-msgid "Writes X3g to files"
-msgstr "Schreibt X3g in Dateien"
-
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:21
-msgctxt "X3g Writer File Description"
-msgid "X3g File"
-msgstr "X3g-Datei"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "Print in Progress"
+msgstr "Druck in Bearbeitung"
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
@@ -148,6 +127,7 @@ msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeWriter unterstützt keinen Textmodus."
#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:28
+#: /home/ruben/Projects/Cura/plugins/UFPReader/__init__.py:22
msgctxt "@item:inlistbox"
msgid "Ultimaker Format Package"
msgstr "Ultimaker Format Package"
@@ -169,7 +149,7 @@ msgid "Save to Removable Drive {0}"
msgstr "Auf Wechseldatenträger speichern {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:107
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "Es sind keine Dateiformate zum Schreiben vorhanden!"
@@ -206,10 +186,9 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "Konnte nicht auf dem Wechseldatenträger gespeichert werden {0}: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:152
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1629
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:139
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1668
msgctxt "@info:title"
msgid "Error"
msgstr "Fehler"
@@ -238,9 +217,9 @@ msgstr "Wechseldatenträger auswerfen {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:151
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:163
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1619
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1719
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1658
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1758
msgctxt "@info:title"
msgid "Warning"
msgstr "Warnhinweis"
@@ -267,337 +246,164 @@ msgctxt "@item:intext"
msgid "Removable Drive"
msgstr "Wechseldatenträger"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:74
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py:26
+msgctxt "@action"
+msgid "Connect via Network"
+msgstr "Anschluss über Netzwerk"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:57
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Drucken über Netzwerk"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:58
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Drücken über Netzwerk"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
-msgctxt "@info:status"
-msgid "Connected over the network."
-msgstr "Über Netzwerk verbunden."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
-msgctxt "@info:status"
-msgid "Connected over the network. Please approve the access request on the printer."
-msgstr "Über Netzwerk verbunden. Geben Sie die Zugriffsanforderung für den Drucker frei."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:93
-msgctxt "@info:status"
-msgid "Connected over the network. No access to control the printer."
-msgstr "Über Netzwerk verbunden. Kein Zugriff auf die Druckerverwaltung."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
-msgctxt "@info:status"
-msgid "Access to the printer requested. Please approve the request on the printer"
-msgstr "Zugriff auf Drucker erforderlich. Bestätigen Sie den Zugriff auf den Drucker"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:101
-msgctxt "@info:title"
-msgid "Authentication status"
-msgstr "Authentifizierungsstatus"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
-msgctxt "@info:title"
-msgid "Authentication Status"
-msgstr "Authentifizierungsstatus"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:187
-msgctxt "@action:button"
-msgid "Retry"
-msgstr "Erneut versuchen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
-msgctxt "@info:tooltip"
-msgid "Re-send the access request"
-msgstr "Zugriffanforderung erneut senden"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
-msgctxt "@info:status"
-msgid "Access to the printer accepted"
-msgstr "Zugriff auf den Drucker genehmigt"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
-msgctxt "@info:status"
-msgid "No access to print with this printer. Unable to send print job."
-msgstr "Kein Zugriff auf das Drucken mit diesem Drucker. Druckauftrag kann nicht gesendet werden."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:65
-msgctxt "@action:button"
-msgid "Request Access"
-msgstr "Zugriff anfordern"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:66
-msgctxt "@info:tooltip"
-msgid "Send access request to the printer"
-msgstr "Zugriffsanforderung für den Drucker senden"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:201
-msgctxt "@label"
-msgid "Unable to start a new print job."
-msgstr "Es kann kein neuer Druckauftrag gestartet werden."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:203
-msgctxt "@label"
-msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
-msgstr "Es liegt ein Problem mit der Konfiguration Ihres Ultimaker vor, das den Druckstart verhindert. Lösen Sie dieses Problem bitte, bevor Sie fortfahren."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:209
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:231
-msgctxt "@window:title"
-msgid "Mismatched configuration"
-msgstr "Konfiguration nicht übereinstimmend"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:223
-msgctxt "@label"
-msgid "Are you sure you wish to print with the selected configuration?"
-msgstr "Möchten Sie wirklich mit der gewählten Konfiguration drucken?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:225
-msgctxt "@label"
-msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Anforderungen zwischen der Druckerkonfiguration oder -kalibrierung und Cura stimmen nicht überein. Für optimale Ergebnisse schneiden Sie stets für die PrintCores und Materialien, die in Ihren Drucker eingelegt wurden."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:252
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:162
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:162
-msgctxt "@info:status"
-msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
-msgstr "Das Senden neuer Aufträge ist (vorübergehend) blockiert; der vorherige Druckauftrag wird noch gesendet."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:180
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
-msgctxt "@info:status"
-msgid "Sending data to printer"
-msgstr "Daten werden zum Drucker gesendet"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:182
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:199
-msgctxt "@info:title"
-msgid "Sending Data"
-msgstr "Daten werden gesendet"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:200
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:395
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:38
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:391
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:254
-msgctxt "@action:button"
-msgid "Cancel"
-msgstr "Abbrechen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:324
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr "Kein PrintCore geladen in Steckplatz {slot_number}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:330
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No material loaded in slot {slot_number}"
-msgstr "Kein Material geladen in Steckplatz {slot_number}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:353
-#, python-brace-format
-msgctxt "@label"
-msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
-msgstr "Abweichender PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) für Extruder gewählt {extruder_id}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:362
-#, python-brace-format
-msgctxt "@label"
-msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr "Abweichendes Material (Cura: {0}, Drucker: {1}) für Extruder {2} gewählt"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:548
-msgctxt "@window:title"
-msgid "Sync with your printer"
-msgstr "Synchronisieren Ihres Druckers"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:550
-msgctxt "@label"
-msgid "Would you like to use your current printer configuration in Cura?"
-msgstr "Möchten Sie Ihre aktuelle Druckerkonfiguration in Cura verwenden?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:552
-msgctxt "@label"
-msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Die PrintCores und/oder Materialien auf Ihrem Drucker unterscheiden sich von denen Ihres aktuellen Projekts. Für optimale Ergebnisse schneiden Sie stets für die PrintCores und Materialien, die in Ihren Drucker eingelegt wurden."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:59
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Über Netzwerk verbunden"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:275
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:342
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:15
+msgctxt "@info:status"
+msgid "Please wait until the current job has been sent."
+msgstr "Bitte warten Sie, bis der aktuelle Druckauftrag gesendet wurde."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:16
+msgctxt "@info:title"
+msgid "Print error"
+msgstr "Druckfehler"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:21
+msgctxt "@info:title"
+msgid "New cloud printers found"
+msgstr "Neue Cloud-Drucker gefunden"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:22
+msgctxt "@info:message"
+msgid "New printers have been found connected to your account, you can find them in your list of discovered printers."
+msgstr "Es wurden neue Drucker gefunden, die Sie zu Ihrem Konto hinzufügen können. Sie finden diese in der Liste gefundener Drucker."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:27
+msgctxt "@info:option_text"
+msgid "Do not show this message again"
+msgstr "Diese Meldung nicht mehr anzeigen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:27
+#, python-brace-format
+msgctxt "@info:status"
+msgid "You are attempting to connect to {0} but it is not the host of a group. You can visit the web page to configure it as a group host."
+msgstr "Sie versuchen, sich mit {0} zu verbinden, aber dieser Drucker ist nicht der Host, der die Gruppe verwaltet. Besuchen Sie die Website, um den Drucker als Host der Gruppe zu konfigurieren."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:30
+msgctxt "@info:title"
+msgid "Not a group host"
+msgstr "Nicht Host-Drucker der Gruppe"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:35
+msgctxt "@action"
+msgid "Configure group"
+msgstr "Gruppe konfigurieren"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:27
+msgctxt "@info:status"
+msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
+msgstr "Druckaufträge mithilfe Ihres Ultimaker-Kontos von einem anderen Ort aus senden und überwachen."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:33
+msgctxt "@info:status Ultimaker Cloud should not be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Verbinden mit Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:36
+msgctxt "@action"
+msgid "Get started"
+msgstr "Erste Schritte"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Druckauftrag senden"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading print job to printer."
+msgstr "Druckauftrag wird vorbereitet."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:15
msgctxt "@info:status"
msgid "Print job was successfully sent to the printer."
msgstr "Der Druckauftrag wurde erfolgreich an den Drucker gesendet."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:277
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:343
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:16
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Daten gesendet"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:278
-msgctxt "@action:button"
-msgid "View in Monitor"
-msgstr "In Monitor überwachen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:390
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:290
-#, python-brace-format
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:18
msgctxt "@info:status"
-msgid "Printer '{printer_name}' has finished printing '{job_name}'."
-msgstr "Drucker '{printer_name}' hat '{job_name}' vollständig gedrückt."
+msgid "You are attempting to connect to a printer that is not running Ultimaker Connect. Please update the printer to the latest firmware."
+msgstr "Sie versuchen, sich mit einem Drucker zu verbinden, auf dem Ultimaker Connect nicht läuft. Bitte aktualisieren Sie die Firmware des Druckers."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:392
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:294
-#, python-brace-format
-msgctxt "@info:status"
-msgid "The print job '{job_name}' was finished."
-msgstr "Der Druckauftrag '{job_name}' wurde ausgeführt."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:393
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:289
-msgctxt "@info:status"
-msgid "Print finished"
-msgstr "Druck vollendet"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:573
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:607
-msgctxt "@label:material"
-msgid "Empty"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:574
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:608
-msgctxt "@label:material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:151
-msgctxt "@action:button"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:152
-msgctxt "@properties:tooltip"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:153
-msgctxt "@info:status"
-msgid "Connected via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:163
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:21
msgctxt "@info:title"
-msgid "Cloud error"
-msgstr ""
+msgid "Update your printer"
+msgstr "Drucker aktualisieren"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:180
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:24
+#, python-brace-format
msgctxt "@info:status"
-msgid "Could not export print job."
-msgstr ""
+msgid "Cura has detected material profiles that were not yet installed on the host printer of group {0}."
+msgstr "Cura hat Materialprofile entdeckt, die auf dem Host-Drucker der Gruppe {0} noch nicht installiert wurden."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:330
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:26
+msgctxt "@info:title"
+msgid "Sending materials to printer"
+msgstr "Material an Drucker senden"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:15
msgctxt "@info:text"
msgid "Could not upload the data to the printer."
-msgstr ""
+msgstr "Daten konnten nicht in Drucker geladen werden."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:16
+msgctxt "@info:title"
+msgid "Network error"
+msgstr "Netzwerkfehler"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:27
msgctxt "@info:status"
msgid "tomorrow"
-msgstr ""
+msgstr "morgen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:30
msgctxt "@info:status"
msgid "today"
-msgstr ""
+msgstr "heute"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:151
-msgctxt "@info:description"
-msgid "There was an error connecting to the cloud."
-msgstr ""
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:138
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Über Cloud drucken"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:139
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Über Cloud drucken"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:140
msgctxt "@info:status"
-msgid "Sending data to remote cluster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:456
-msgctxt "@info:status"
-msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:460
-msgctxt "@info:status"
-msgid "Connect to Ultimaker Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:461
-msgctxt "@action"
-msgid "Don't ask me again for this printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:464
-msgctxt "@action"
-msgid "Get started"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:478
-msgctxt "@info:status"
-msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:482
-msgctxt "@info:status"
-msgid "Connected!"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:486
-msgctxt "@action"
-msgid "Review your connection"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
-msgctxt "@action"
-msgid "Connect via Network"
-msgstr "Anschluss über Netzwerk"
+msgid "Connected via Cloud"
+msgstr "Über Cloud verbunden"
#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Überwachen"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:124
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:125
msgctxt "@info"
msgid "Could not access update information."
msgstr "Zugriff auf Update-Informationen nicht möglich."
@@ -624,12 +430,12 @@ msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Schichtenansicht"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:117
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Cura zeigt die Schichten nicht akkurat an, wenn Wire Printing aktiviert ist"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:118
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Simulationsansicht"
@@ -637,12 +443,12 @@ msgstr "Simulationsansicht"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
msgctxt "@item:inmenu"
msgid "Post Processing"
-msgstr ""
+msgstr "Nachbearbeitung"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
msgctxt "@item:inmenu"
msgid "Modify G-Code"
-msgstr ""
+msgstr "G-Code ändern"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12
msgctxt "@label"
@@ -654,46 +460,11 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr "Erstellt ein Volumen, in dem keine Stützstrukturen gedruckt werden."
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr "Cura erfasst anonymisierte Nutzungsstatistiken."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:55
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Daten werden erfasst"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:57
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Mehr Infos"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:58
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr "Siehe mehr Informationen dazu, was Cura sendet."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:60
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Zulassen"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:61
-msgctxt "@action:tooltip"
-msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
-msgstr "Damit lassen Sie zu, dass Cura anonymisierte Nutzungsstatistiken sendet, um zukünftige Verbesserungen für Cura zu definieren. Einige Ihrer Präferenzen und Einstellungen, die Cura-Version und ein Hash der Modelle, die Sie slicen, werden gesendet."
-
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Cura 15.04-Profile"
-#: /home/ruben/Projects/Cura/plugins/R2D2/__init__.py:17
-msgctxt "@item:inmenu"
-msgid "Evaluation"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/ImageReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "JPG Image"
@@ -719,56 +490,86 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "GIF-Bilddatei"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:15
+msgctxt "@item:inlistbox 'Open' is part of the name of this file format."
+msgid "Open Compressed Triangle Mesh"
+msgstr "Öffnen Sie das komprimierte Dreiecksnetz"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:19
+msgctxt "@item:inlistbox"
+msgid "COLLADA Digital Asset Exchange"
+msgstr "COLLADA Digital Asset Exchange"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:23
+msgctxt "@item:inlistbox"
+msgid "glTF Binary"
+msgstr "glTF Binary"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:27
+msgctxt "@item:inlistbox"
+msgid "glTF Embedded JSON"
+msgstr "glTF Embedded JSON"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:36
+msgctxt "@item:inlistbox"
+msgid "Stanford Triangle Format"
+msgstr "Stanford Triangle Format"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:40
+msgctxt "@item:inlistbox"
+msgid "Compressed COLLADA Digital Asset Exchange"
+msgstr "Compressed COLLADA Digital Asset Exchange"
+
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
msgctxt "@info:status"
msgid "Unable to slice with the current material as it is incompatible with the selected machine or configuration."
msgstr "Slicing mit dem aktuellen Material nicht möglich, da es mit der gewählten Maschine oder Konfiguration nicht kompatibel ist."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:389
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:398
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:407
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:416
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:362
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:386
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:395
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:404
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:413
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "Slicing nicht möglich"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "Die aktuellen Einstellungen lassen kein Schneiden (Slicing) zu. Die folgenden Einstellungen sind fehlerhaft:{0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}"
msgstr "Aufgrund der Pro-Modell-Einstellungen ist kein Schneiden (Slicing) möglich. Die folgenden Einstellungen sind für ein oder mehrere Modelle fehlerhaft: {error_labels}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:394
msgctxt "@info:status"
msgid "Unable to slice because the prime tower or prime position(s) are invalid."
msgstr "Schneiden (Slicing) ist nicht möglich, da der Einzugsturm oder die Einzugsposition(en) ungültig ist (sind)."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid "Unable to slice because there are objects associated with disabled Extruder %s."
msgstr "Schneiden (Slicing) ist nicht möglich, da Objekte vorhanden sind, die mit dem deaktivierten Extruder %s verbunden sind."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:412
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume or are assigned to a disabled extruder. Please scale or rotate models to fit, or enable an extruder."
-msgstr ""
+msgstr "Es ist kein Objekt zum Schneiden vorhanden, da keines der Modelle den Druckabmessungen entspricht oder weil sie einem deaktivierten Extruder zugewiesen wurden. Bitte die Modelle passend skalieren oder drehen."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Schichten werden verarbeitet"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Informationen"
@@ -783,12 +584,12 @@ msgctxt "@info:tooltip"
msgid "Configure Per Model Settings"
msgstr "Pro Objekteinstellungen konfigurieren"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:186
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Empfohlen"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:188
msgctxt "@title:tab"
msgid "Custom"
msgstr "Benutzerdefiniert"
@@ -799,19 +600,19 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "3MF-Datei"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:190
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:763
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:198
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:651
msgctxt "@label"
msgid "Nozzle"
msgstr "Düse"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:469
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:496
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Project file {0} contains an unknown machine type {1}. Cannot import the machine. Models will be imported instead."
msgstr "Projektdatei {0} enthält einen unbekannten Maschinentyp {1}. Importieren der Maschine ist nicht möglich. Stattdessen werden die Modelle importiert."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:472
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:499
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Projektdatei öffnen"
@@ -826,18 +627,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "G-Datei"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:324
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:335
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "G-Code parsen"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:326
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:476
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:337
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:491
msgctxt "@info:title"
msgid "G-code Details"
msgstr "G-Code-Details"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:474
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:489
msgctxt "@info:generic"
msgid "Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."
msgstr "Stellen Sie sicher, dass der G-Code für Ihren Drucker und Ihre Druckerkonfiguration geeignet ist, bevor Sie die Datei senden. Der Darstellung des G-Codes ist möglicherweise nicht korrekt."
@@ -845,7 +646,7 @@ msgstr "Stellen Sie sicher, dass der G-Code für Ihren Drucker und Ihre Druckerk
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
msgctxt "@item:inmenu"
msgid "Manage backups"
-msgstr ""
+msgstr "Backups verwalten"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
@@ -858,32 +659,32 @@ msgstr "Backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
msgctxt "@info:backup_status"
msgid "There was an error listing your backups."
-msgstr ""
+msgstr "Beim Versuch, Ihre Backups aufzulisten, trat ein Fehler auf."
-#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:121
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:132
msgctxt "@info:backup_status"
msgid "There was an error trying to restore your backup."
-msgstr ""
+msgstr "Beim Versuch, Ihr Backup wiederherzustellen, trat ein Fehler auf."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:15
msgctxt "@info:title"
msgid "Backups"
-msgstr ""
+msgstr "Backups"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
msgctxt "@info:backup_status"
msgid "Uploading your backup..."
-msgstr ""
+msgstr "Ihr Backup wird hochgeladen..."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:36
msgctxt "@info:backup_status"
msgid "There was an error while uploading your backup."
-msgstr ""
+msgstr "Beim Versuch, Ihr Backup hochzuladen, trat ein Fehler auf."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:39
msgctxt "@info:backup_status"
msgid "Your backup has finished uploading."
-msgstr ""
+msgstr "Ihr Backup wurde erfolgreich hochgeladen."
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
@@ -891,16 +692,6 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Cura-Profil"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
-msgctxt "@item:inmenu"
-msgid "Profile Assistant"
-msgstr "Profilassistent"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
-msgctxt "@item:inlistbox"
-msgid "Profile Assistant"
-msgstr "Profilassistent"
-
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:26
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -919,274 +710,364 @@ msgstr "Fehler beim Schreiben von 3MF-Datei."
#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
msgctxt "@item:inmenu"
msgid "Preview"
-msgstr ""
+msgstr "Vorschau"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Upgrades wählen"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
-msgctxt "@action"
-msgid "Checkup"
-msgstr "Check-up"
-
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
msgstr "Druckbett nivellieren"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:81
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Außenwand"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:82
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Innenwände"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:83
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Außenhaut"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:84
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Füllung"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:85
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Stützstruktur-Füllung"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:86
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Stützstruktur-Schnittstelle"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:87
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Stützstruktur"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:88
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Skirt"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Bewegungen"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Einzüge"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Sonstige"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:309
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Vorgeschnittene Datei {0}"
-
-#: /home/ruben/Projects/Cura/cura/API/Account.py:77
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
msgctxt "@info:title"
msgid "Login failed"
msgstr "Login fehlgeschlagen"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:201
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:36
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "Nicht unterstützt"
+
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:55
+msgctxt "@info:No intent profile selected"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:196
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:125
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Datei bereits vorhanden"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:202
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:197
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:126
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Die Datei {0} ist bereits vorhanden. Soll die Datei wirklich überschrieben werden?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:425
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:428
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:433
msgctxt "@info:status"
msgid "Invalid file URL:"
-msgstr ""
+msgstr "Ungültige Datei-URL:"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:206
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "Nicht überschrieben"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:780
+msgctxt "@info:message Followed by a list of settings."
+msgid "Settings have been changed to match the current availability of extruders:"
+msgstr "Die Einstellungen wurden an die aktuell verfügbaren Extruder angepasst:"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:915
-#, python-format
-msgctxt "@info:generic"
-msgid "Settings have been changed to match the current availability of extruders: [%s]"
-msgstr "Die Einstellungen wurden passend für die aktuelle Verfügbarkeit der Extruder geändert: [%s]"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:917
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:782
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Einstellungen aktualisiert"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1458
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1334
msgctxt "@info:title"
msgid "Extruder(s) Disabled"
-msgstr ""
+msgstr "Extruder deaktiviert"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1457
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:99
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:86
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:182
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:223
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:137
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "Export des Profils nach {0} fehlgeschlagen: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:138
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "Export des Profils nach {0} fehlgeschlagen: Fehlermeldung von Writer-Plugin."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:149
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "Profil wurde nach {0} exportiert"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:150
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Export erfolgreich ausgeführt"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr ""
-
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
-msgid "Can't import profile from {0} before a printer is added."
-msgstr ""
+msgid "Failed to import profile from {0}: {1}"
+msgstr "Import des Profils aus Datei {0}: {1} fehlgeschlagen"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:181
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags !"
+msgid "Can't import profile from {0} before a printer is added."
+msgstr "Import des Profils aus Datei {0} kann erst durchgeführt werden, wenn ein Drucker hinzugefügt wurde."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:198
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "No custom profile to import in file {0}"
msgstr "Kein benutzerdefiniertes Profil für das Importieren in Datei {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:202
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}:"
msgstr "Import des Profils aus Datei {0} fehlgeschlagen:"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:226
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:236
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "This profile {0} contains incorrect data, could not import it."
msgstr "Dieses Profil {0} enthält falsche Daten, Importieren nicht möglich."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:241
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:325
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
-msgstr "Die Maschine, die im Profil {0} ({1}) definiert wurde, entspricht nicht Ihrer derzeitigen Maschine ({2}). Importieren nicht möglich."
-
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to import profile from {0}:"
msgstr "Import des Profils aus Datei {0} fehlgeschlagen:"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:328
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Profil erfolgreich importiert {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:319
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:331
#, python-brace-format
msgctxt "@info:status"
msgid "File {0} does not contain any valid profile."
msgstr "Datei {0} enthält kein gültiges Profil."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:322
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:334
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "Profil {0} hat einen unbekannten Dateityp oder ist beschädigt."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:340
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:369
msgctxt "@label"
msgid "Custom profile"
msgstr "Benutzerdefiniertes Profil"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:385
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "Für das Profil fehlt eine Qualitätsangabe."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:370
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:399
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "Es konnte keine Qualitätsangabe {0} für die vorliegende Konfiguration gefunden werden."
-#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:69
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:76
+msgctxt "@tooltip"
+msgid "Outer Wall"
+msgstr "Außenwand"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:77
+msgctxt "@tooltip"
+msgid "Inner Walls"
+msgstr "Innenwände"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:78
+msgctxt "@tooltip"
+msgid "Skin"
+msgstr "Außenhaut"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:79
+msgctxt "@tooltip"
+msgid "Infill"
+msgstr "Füllung"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:80
+msgctxt "@tooltip"
+msgid "Support Infill"
+msgstr "Stützstruktur-Füllung"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:81
+msgctxt "@tooltip"
+msgid "Support Interface"
+msgstr "Stützstruktur-Schnittstelle"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:82
+msgctxt "@tooltip"
+msgid "Support"
+msgstr "Stützstruktur"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:83
+msgctxt "@tooltip"
+msgid "Skirt"
+msgstr "Skirt"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:84
+msgctxt "@tooltip"
+msgid "Prime Tower"
+msgstr "Einzugsturm"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:85
+msgctxt "@tooltip"
+msgid "Travel"
+msgstr "Bewegungen"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:86
+msgctxt "@tooltip"
+msgid "Retractions"
+msgstr "Einzüge"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:87
+msgctxt "@tooltip"
+msgid "Other"
+msgstr "Sonstige"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:302
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "Vorgeschnittene Datei {0}"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Weiter"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:62
#, python-brace-format
msgctxt "@label"
msgid "Group #{group_nr}"
msgstr "Gruppe #{group_nr}"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:65
-msgctxt "@info:title"
-msgid "Network enabled printers"
-msgstr "Netzwerkfähige Drucker"
+#: /home/ruben/Projects/Cura/cura/UI/WhatsNewPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:169
+msgctxt "@action:button"
+msgid "Close"
+msgstr "Schließen"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:80
-msgctxt "@info:title"
-msgid "Local printers"
-msgstr "Lokale Drucker"
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Hinzufügen"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:18
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:352
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:58
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:149
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:406
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:294
+msgctxt "@action:button"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:36
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:320
+msgctxt "@label"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:39
+msgctxt "@label"
+msgid "Visual"
+msgstr "Visuell"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:40
+msgctxt "@text"
+msgid "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality."
+msgstr "Das visuelle Profil wurde für den Druck visueller Prototypen und Modellen entwickelt, bei denen das Ziel eine hohe visuelle Qualität und eine hohe Oberflächenqualität"
+" ist."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:43
+msgctxt "@label"
+msgid "Engineering"
+msgstr "Engineering"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:44
+msgctxt "@text"
+msgid "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances."
+msgstr "Das Engineering-Profil ist für den Druck von Funktionsprototypen und Endnutzungsteilen gedacht, bei denen Präzision gefragt ist und engere Toleranzen gelten."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:47
+msgctxt "@label"
+msgid "Draft"
+msgstr "Entwurf"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:48
+msgctxt "@text"
+msgid "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction."
+msgstr "Das Entwurfsprofil wurde für erste Prototypen und die Konzeptvalidierung entwickelt, um einen deutlich schnelleren Druck zu ermöglichen."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr "Nicht überschrieben"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:357
+msgctxt "@label"
+msgid "Custom profiles"
+msgstr "Benutzerdefinierte Profile"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:391
#, python-brace-format
msgctxt "@item:inlistbox"
msgid "All Supported Types ({0})"
msgstr "Alle unterstützten Typen ({0})"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:110
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:392
msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Alle Dateien (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:665
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:213
msgctxt "@label"
msgid "Custom Material"
msgstr "Benutzerdefiniertes Material"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:666
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:256
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:214
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:205
msgctxt "@label"
msgid "Custom"
msgstr "Benutzerdefiniert"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:116
+msgctxt "@label"
+msgid "The printer(s) below cannot be connected because they are part of a group"
+msgstr "Der/die nachfolgende(n) Drucker kann/können nicht verbunden werden, weil er/sie Teil einer Gruppe ist/sind"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:118
+msgctxt "@label"
+msgid "Available networked printers"
+msgstr "Verfügbare vernetzte Drucker"
+
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:90
msgctxt "@info:status"
msgid "The build volume height has been reduced due to the value of the \"Print Sequence\" setting to prevent the gantry from colliding with printed models."
msgstr "Die Höhe der Druckabmessung wurde aufgrund des Wertes der Einstellung „Druckreihenfolge“ reduziert, um eine Kollision der Brücke mit den gedruckten Modellen zu verhindern."
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:83
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:92
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Produktabmessungen"
@@ -1201,52 +1082,67 @@ msgctxt "@info:backup_failed"
msgid "Tried to restore a Cura backup without having proper data or meta data."
msgstr "Versucht, ein Cura-Backup-Verzeichnis ohne entsprechende Daten oder Metadaten wiederherzustellen."
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:124
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:125
msgctxt "@info:backup_failed"
-msgid "Tried to restore a Cura backup that does not match your current version."
-msgstr "Versucht, ein Cura-Backup zu erstellen, das nicht Ihrer aktuellen Version entspricht."
+msgid "Tried to restore a Cura backup that is higher than the current version."
+msgstr "Versucht, ein Cura-Backup wiederherzustellen, das eine höhere Version als die aktuelle hat."
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr "Antwort konnte nicht gelesen werden."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
msgctxt "@info"
msgid "Unable to reach the Ultimaker account server."
-msgstr ""
+msgstr "Der Ultimaker-Konto-Server konnte nicht erreicht werden."
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:70
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr "Erteilen Sie bitte die erforderlichen Freigaben bei der Autorisierung dieser Anwendung."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:77
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
+msgstr "Bei dem Versuch, sich anzumelden, trat ein unerwarteter Fehler auf. Bitte erneut versuchen."
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:29
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Objekte vervielfältigen und platzieren"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:30
msgctxt "@info:title"
msgid "Placing Objects"
-msgstr ""
+msgstr "Objekte platzieren"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:149
msgctxt "@info:status"
msgid "Unable to find a location within the build volume for all objects"
msgstr "Innerhalb der Druckabmessung für alle Objekte konnte keine Position gefunden werden"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Objekt-Platzierung"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:30
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:67
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:66
msgctxt "@info:status"
msgid "Finding new location for objects"
msgstr "Neue Position für Objekte finden"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:34
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:71
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:70
msgctxt "@info:title"
msgid "Finding Location"
msgstr "Position finden"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Kann Position nicht finden"
@@ -1377,242 +1273,205 @@ msgstr "Protokolle"
#: /home/ruben/Projects/Cura/cura/CrashHandler.py:322
msgctxt "@title:groupbox"
-msgid "User description"
-msgstr "Benutzerbeschreibung"
+msgid "User description (Note: Developers may not speak your language, please use English if possible)"
+msgstr "Benutzerbeschreibung (Hinweis: Bitte schreiben Sie auf Englisch, da die Entwickler Ihre Sprache möglicherweise nicht beherrschen.)"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:341
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Bericht senden"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:480
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:513
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Geräte werden geladen..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:781
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:520
+msgctxt "@info:progress"
+msgid "Setting up preferences..."
+msgstr "Erstellungen werden eingerichtet ..."
+
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:824
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Die Szene wird eingerichtet..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:817
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:859
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Die Benutzeroberfläche wird geladen..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1059
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1150
#, python-format
msgctxt "@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm."
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr "%(width).1f x %(depth).1f x %(height).1f mm"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1618
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1657
#, python-brace-format
msgctxt "@info:status"
msgid "Only one G-code file can be loaded at a time. Skipped importing {0}"
msgstr "Es kann nur jeweils ein G-Code gleichzeitig geladen werden. Wichtige {0} werden übersprungen."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1628
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1667
#, python-brace-format
msgctxt "@info:status"
msgid "Can't open any other file if G-code is loading. Skipped importing {0}"
msgstr "Wenn G-Code geladen wird, kann keine weitere Datei geöffnet werden. Wichtige {0} werden übersprungen."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1718
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1757
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "Das gewählte Modell war zu klein zum Laden."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:62
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Geräteeinstellungen"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:81
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Drucker"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:100
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:56
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Druckereinstellungen"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:70
msgctxt "@label"
msgid "X (Width)"
msgstr "X (Breite)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:112
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:122
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:132
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:387
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:429
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:441
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:897
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:74
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:88
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:102
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:243
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:265
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:285
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:79
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:93
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:109
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:124
msgctxt "@label"
msgid "mm"
msgstr "mm"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:84
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (Tiefe)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:98
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (Höhe)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:143
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:112
msgctxt "@label"
msgid "Build plate shape"
msgstr "Druckbettform"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:152
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:125
+msgctxt "@label"
msgid "Origin at center"
msgstr "Ausgang in Mitte"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:160
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:137
+msgctxt "@label"
msgid "Heated bed"
msgstr "Heizbares Bett"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:171
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:149
+msgctxt "@label"
+msgid "Heated build volume"
+msgstr "Druckraum aufgeheizt"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:161
msgctxt "@label"
msgid "G-code flavor"
msgstr "G-Code-Variante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:184
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:185
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Druckkopfeinstellungen"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:199
msgctxt "@label"
msgid "X min"
msgstr "X min."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:195
-msgctxt "@tooltip"
-msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Abstand von der linken Seite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:219
msgctxt "@label"
msgid "Y min"
msgstr "Y min."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:205
-msgctxt "@tooltip"
-msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Abstand von der Vorderseite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:239
msgctxt "@label"
msgid "X max"
msgstr "X max."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:215
-msgctxt "@tooltip"
-msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Abstand von der rechten Seite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:261
msgctxt "@label"
msgid "Y max"
msgstr "Y max."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:225
-msgctxt "@tooltip"
-msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Abstand von der Rückseite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:281
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Brückenhöhe"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:239
-msgctxt "@tooltip"
-msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
-msgstr "Der Höhenunterschied zwischen der Düsenspitze und dem Brückensystem (X- und Y-Achsen). Wird verwendet, um Kollisionen zwischen vorherigen Drucken und der Brücke zu verhindern, wenn im Modus „Nacheinander“ gedruckt wird."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:258
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:295
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Anzahl Extruder"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:314
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "Start G-code"
-msgstr "Start G-code"
+msgstr "Start G-Code"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:324
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr "G-Code-Befehle, die zum Start ausgeführt werden sollen."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:333
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:366
+msgctxt "@title:label"
msgid "End G-code"
-msgstr "Ende G-code"
+msgstr "Ende G-Code"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:343
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very end."
-msgstr "G-Code-Befehle, die am Ende ausgeführt werden sollen."
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:42
+msgctxt "@title:tab"
+msgid "Printer"
+msgstr "Drucker"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:374
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:63
+msgctxt "@title:label"
msgid "Nozzle Settings"
msgstr "Düseneinstellungen"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr "Düsengröße"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr "Kompatibler Materialdurchmesser"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:404
-msgctxt "@tooltip"
-msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
-msgstr "Der Nenndurchmesser des durch den Drucker unterstützten Filaments. Der exakte Durchmesser wird durch das Material und/oder das Profil überschrieben."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:428
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "X-Versatz Düse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:440
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:120
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Y-Versatz Düse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:452
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:135
msgctxt "@label"
msgid "Cooling Fan Number"
msgstr "Kühllüfter-Nr."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:453
-msgctxt "@label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:473
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "G-Code Extruder-Start"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:491
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "G-Code Extruder-Ende"
@@ -1622,7 +1481,7 @@ msgid "Install"
msgstr "Installieren"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Installiert"
@@ -1635,18 +1494,18 @@ msgstr "Verbindung zur Cura Paket-Datenbank konnte nicht hergestellt werden. Bit
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
msgctxt "@label"
msgid "ratings"
-msgstr ""
+msgstr "Bewertungen"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:28
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:32
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:30
msgctxt "@title:tab"
msgid "Plugins"
msgstr "Plugins"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:69
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:42
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:361
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:77
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materialien"
@@ -1654,54 +1513,51 @@ msgstr "Materialien"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
msgctxt "@label"
msgid "Your rating"
-msgstr ""
+msgstr "Ihre Bewertung"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:98
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:99
msgctxt "@label"
msgid "Version"
msgstr "Version"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:105
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:106
msgctxt "@label"
msgid "Last updated"
msgstr "Zuletzt aktualisiert"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:112
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:260
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:113
msgctxt "@label"
msgid "Author"
msgstr "Autor"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:119
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:120
msgctxt "@label"
msgid "Downloads"
msgstr "Downloads"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:181
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:222
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:265
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Unbekannt"
-
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:56
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to install or update"
-msgstr ""
+msgstr "Anmeldung für Installation oder Update erforderlich"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:73
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:80
+msgctxt "@label:The string between and is the highlighted link"
+msgid "Buy material spools"
+msgstr "Materialspulen kaufen"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:96
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:34
msgctxt "@action:button"
msgid "Update"
msgstr "Aktualisierung"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:74
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:97
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:35
msgctxt "@action:button"
msgid "Updating"
msgstr "Aktualisierung wird durchgeführt"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:75
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:98
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:36
msgctxt "@action:button"
msgid "Updated"
@@ -1710,7 +1566,7 @@ msgstr "Aktualisiert"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
msgid "Marketplace"
-msgstr ""
+msgstr "Marktplatz"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1745,12 +1601,12 @@ msgstr "Bestätigen"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to login first before you can rate"
-msgstr ""
+msgstr "Vor der Bewertung müssen Sie sich anmelden"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to install the package before you can rate"
-msgstr ""
+msgstr "Vor der Bewertung müssen Sie das Paket installierten"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
@@ -1762,22 +1618,22 @@ msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Quit Cura"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Contributions"
msgstr "Community-Beiträge"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Plugins"
msgstr "Community-Plugins"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:43
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:40
msgctxt "@label"
msgid "Generic Materials"
msgstr "Generische Materialien"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:56
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Installiert"
@@ -1790,7 +1646,7 @@ msgstr "Installiert nach Neustart"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:53
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to update"
-msgstr ""
+msgstr "Anmeldung für Update erforderlich"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
@@ -1833,42 +1689,62 @@ msgctxt "@label"
msgid "Featured"
msgstr "Unterstützter"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:34
msgctxt "@label"
msgid "Compatibility"
msgstr "Kompatibilität"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:124
+msgctxt "@label:table_header"
+msgid "Machine"
+msgstr "Gerät"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:137
+msgctxt "@label:table_header"
+msgid "Build Plate"
+msgstr "Druckbett"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:143
+msgctxt "@label:table_header"
+msgid "Support"
+msgstr "Support"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:149
+msgctxt "@label:table_header"
+msgid "Quality"
+msgstr "Qualität"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:170
msgctxt "@action:label"
msgid "Technical Data Sheet"
-msgstr ""
+msgstr "Technisches Datenblatt"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:179
msgctxt "@action:label"
msgid "Safety Data Sheet"
-msgstr ""
+msgstr "Sicherheitsdatenblatt"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:188
msgctxt "@action:label"
msgid "Printing Guidelines"
-msgstr ""
+msgstr "Druckrichtlinien"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:197
msgctxt "@action:label"
msgid "Website"
-msgstr ""
+msgstr "Website"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml:16
msgctxt "@info"
msgid "Fetching packages..."
msgstr "Pakete werden abgeholt..."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:90
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:91
msgctxt "@label"
msgid "Website"
msgstr "Website"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:97
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "E-Mail"
@@ -1878,22 +1754,6 @@ msgctxt "@info:tooltip"
msgid "Some things could be problematic in this print. Click to see tips for adjustment."
msgstr "Einige Punkte bei diesem Druck könnten problematisch sein. Klicken Sie, um Tipps für die Anpassung zu erhalten."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
-msgctxt "@label"
-msgid "Changelog"
-msgstr "Änderungsprotokoll"
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:85
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
-msgctxt "@action:button"
-msgid "Close"
-msgstr "Schließen"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
msgctxt "@title"
msgid "Update Firmware"
@@ -1969,77 +1829,79 @@ msgctxt "@label"
msgid "Firmware update failed due to missing firmware."
msgstr "Die Firmware-Aktualisierung ist aufgrund von fehlender Firmware fehlgeschlagen."
-#: /home/ruben/Projects/Cura/plugins/UserAgreement/UserAgreement.qml:16
-msgctxt "@title:window"
-msgid "User Agreement"
-msgstr "Benutzervereinbarung"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:155
+msgctxt "@label link to Connect and Cloud interfaces"
+msgid "Manage printer"
+msgstr "Drucker verwalten"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:254
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:192
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:183
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
+msgstr "Glas"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:256
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:514
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:248
msgctxt "@info"
-msgid "These options are not available because you are monitoring a cloud printer."
-msgstr ""
+msgid "Please update your printer's firmware to manage the queue remotely."
+msgstr "Damit Sie die Warteschlange aus der Ferne verwalten können, müssen Sie die Druckfirmware aktualisieren."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:289
msgctxt "@info"
msgid "The webcam is not available because you are monitoring a cloud printer."
-msgstr ""
+msgstr "Die Webcam ist nicht verfügbar, weil Sie einen Cloud-Drucker überwachen."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:301
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:348
msgctxt "@label:status"
msgid "Loading..."
-msgstr ""
+msgstr "Lädt..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:305
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:352
msgctxt "@label:status"
msgid "Unavailable"
msgstr "Nicht verfügbar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:309
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:356
msgctxt "@label:status"
msgid "Unreachable"
-msgstr ""
+msgstr "Nicht erreichbar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:360
msgctxt "@label:status"
msgid "Idle"
-msgstr ""
+msgstr "Leerlauf"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
msgctxt "@label"
msgid "Untitled"
-msgstr ""
+msgstr "Unbenannt"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:373
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:422
msgctxt "@label"
msgid "Anonymous"
-msgstr ""
+msgstr "Anonym"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:399
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:449
msgctxt "@label:status"
msgid "Requires configuration changes"
-msgstr ""
+msgstr "Erfordert Konfigurationsänderungen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:436
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:487
msgctxt "@action:button"
msgid "Details"
-msgstr ""
+msgstr "Details"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
msgctxt "@label"
msgid "Unavailable printer"
-msgstr ""
+msgstr "Drucker nicht verfügbar"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:134
msgctxt "@label"
msgid "First available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:187
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:132
-msgctxt "@label"
-msgid "Glass"
-msgstr "Glas"
+msgstr "Zuerst verfügbar"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
msgctxt "@label"
@@ -2048,196 +1910,193 @@ msgstr "In Warteschlange"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
msgctxt "@label link to connect manager"
-msgid "Go to Cura Connect"
-msgstr ""
+msgid "Manage in browser"
+msgstr "Im Browser verwalten"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:100
+msgctxt "@label"
+msgid "There are no print jobs in the queue. Slice and send a job to add one."
+msgstr "Die Warteschlange enthält keine Druckaufträge. Slicen Sie einen Auftrag und schicken Sie ihn ab, um ihn zur Warteschlange hinzuzufügen."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:115
msgctxt "@label"
msgid "Print jobs"
-msgstr ""
+msgstr "Druckaufträge"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:131
msgctxt "@label"
msgid "Total print time"
-msgstr ""
+msgstr "Druckdauer insgesamt"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:130
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:147
msgctxt "@label"
msgid "Waiting for"
-msgstr ""
+msgstr "Warten auf"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:246
-msgctxt "@label link to connect manager"
-msgid "View print history"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:46
-msgctxt "@window:title"
-msgid "Existing Connection"
-msgstr "Vorhandene Verbindung"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:48
-msgctxt "@message:text"
-msgid "This printer/group is already added to Cura. Please select another printer/group."
-msgstr "Diese/r Drucker/Gruppe wurde bereits zu Cura hinzugefügt. Wählen Sie bitte eine/n andere/n Drucker/Gruppe."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:65
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Anschluss an vernetzten Drucker"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
msgctxt "@label"
-msgid ""
-"To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
-"\n"
-"Select your printer from the list below:"
-msgstr ""
-"Um über das Netzwerk direkt auf Ihrem Drucker zu drucken, stellen Sie bitte sicher, dass der Drucker mit dem Netzwerkkabel verbunden ist oder verbinden Sie Ihren Drucker mit Ihrem WLAN-Netzwerk. Wenn Sie Cura nicht mit Ihrem Drucker verbinden, können Sie dennoch ein USB-Laufwerk für die Übertragung von G-Code-Dateien auf Ihren Drucker verwenden.\n"
-"\n"
-"Wählen Sie Ihren Drucker aus der folgenden Liste:"
+msgid "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer."
+msgstr "Um direkt auf Ihrem Drucker über das Netzwerk zu drucken, muss der Drucker über ein Netzwerkkabel oder per WLAN mit dem Netzwerk verbunden sein. Wenn Sie Cura nicht mit Ihrem Drucker verbinden, können Sie G-Code-Dateien auf einen USB-Stick kopieren und diesen am Drucker anschließen."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Hinzufügen"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
+msgctxt "@label"
+msgid "Select your printer from the list below:"
+msgstr "Wählen Sie Ihren Drucker aus der folgenden Liste aus:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:97
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
msgctxt "@action:button"
msgid "Edit"
msgstr "Bearbeiten"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:108
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:138
msgctxt "@action:button"
msgid "Remove"
msgstr "Entfernen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:96
msgctxt "@action:button"
msgid "Refresh"
msgstr "Aktualisieren"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:211
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:176
msgctxt "@label"
msgid "If your printer is not listed, read the network printing troubleshooting guide"
msgstr "Wenn Ihr Drucker nicht aufgeführt ist, lesen Sie die Anleitung für Fehlerbehebung für Netzwerkdruck"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:240
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:258
msgctxt "@label"
msgid "Type"
msgstr "Typ"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:279
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:274
msgctxt "@label"
msgid "Firmware version"
msgstr "Firmware-Version"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:290
msgctxt "@label"
msgid "Address"
msgstr "Adresse"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:317
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:263
msgctxt "@label"
msgid "This printer is not set up to host a group of printers."
msgstr "Dieser Drucker ist nicht eingerichtet um eine Gruppe von Druckern anzusteuern."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:267
msgctxt "@label"
msgid "This printer is the host for a group of %1 printers."
msgstr "Dieser Drucker steuert eine Gruppe von %1 Druckern an."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:332
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:278
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr "Der Drucker unter dieser Adresse hat nicht reagiert."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:337
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
msgctxt "@action:button"
msgid "Connect"
msgstr "Verbinden"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:351
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:296
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Ungültige IP-Adresse"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:146
+msgctxt "@text"
+msgid "Please enter a valid IP address."
+msgstr "Bitte eine gültige IP-Adresse eingeben."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:308
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Druckeradresse"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:374
-msgctxt "@alabel"
-msgid "Enter the IP address or hostname of your printer on the network."
-msgstr "Geben Sie die IP-Adresse oder den Hostnamen Ihres Druckers auf dem Netzwerk ein."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
+msgid "Enter the IP address of your printer on the network."
+msgstr "Geben Sie die IP-Adresse Ihres Druckers in das Netzwerk ein."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:404
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:361
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:138
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
msgstr "OK"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
msgctxt "@label:status"
msgid "Aborted"
msgstr "Abgebrochen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:80
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:82
msgctxt "@label:status"
msgid "Finished"
msgstr "Beendet"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:86
msgctxt "@label:status"
msgid "Preparing..."
-msgstr ""
+msgstr "Vorbereitung..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
msgctxt "@label:status"
msgid "Aborting..."
-msgstr ""
+msgstr "Wird abgebrochen..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
msgctxt "@label:status"
msgid "Pausing..."
-msgstr ""
+msgstr "Wird pausiert..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:104
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
msgctxt "@label:status"
msgid "Paused"
msgstr "Pausiert"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
msgctxt "@label:status"
msgid "Resuming..."
-msgstr ""
+msgstr "Wird fortgesetzt..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:108
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
msgctxt "@label:status"
msgid "Action required"
msgstr "Handlung erforderlich"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:110
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
msgctxt "@label:status"
msgid "Finishes %1 at %2"
-msgstr ""
+msgstr "Fertigstellung %1 auf %2"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:44
-msgctxt "@action:button"
-msgid "Print"
-msgstr "Drucken"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:11
msgctxt "@title:window"
msgid "Print over network"
msgstr "Drucken über Netzwerk"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:52
+msgctxt "@action:button"
+msgid "Print"
+msgstr "Drucken"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:80
msgctxt "@label"
msgid "Printer selection"
msgstr "Druckerauswahl"
@@ -2261,12 +2120,12 @@ msgstr "Zurückkehren"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
msgctxt "@label"
msgid "Pausing..."
-msgstr ""
+msgstr "Wird pausiert..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
msgctxt "@label"
msgid "Resuming..."
-msgstr ""
+msgstr "Wird fortgesetzt..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
@@ -2278,7 +2137,7 @@ msgstr "Pausieren"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Aborting..."
-msgstr ""
+msgstr "Wird abgebrochen..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
@@ -2319,161 +2178,155 @@ msgstr "Drucken abbrechen"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
msgctxt "@title:window"
msgid "Configuration Changes"
-msgstr ""
+msgstr "Konfigurationsänderungen"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
msgctxt "@action:button"
msgid "Override"
-msgstr ""
+msgstr "Überschreiben"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:64
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:85
msgctxt "@label"
msgid "The assigned printer, %1, requires the following configuration change:"
msgid_plural "The assigned printer, %1, requires the following configuration changes:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Der zugewiesene Drucker %1 erfordert die folgende Konfigurationsänderung:"
+msgstr[1] "Der zugewiesene Drucker %1 erfordert die folgenden Konfigurationsänderungen:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:68
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:89
msgctxt "@label"
msgid "The printer %1 is assigned, but the job contains an unknown material configuration."
msgstr "Der Drucker %1 wurde zugewiesen, allerdings enthält der Auftrag eine unbekannte Materialkonfiguration."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:99
msgctxt "@label"
msgid "Change material %1 from %2 to %3."
msgstr "Material %1 von %2 auf %3 wechseln."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:102
msgctxt "@label"
msgid "Load %3 as material %1 (This cannot be overridden)."
msgstr "%3 als Material %1 laden (Dies kann nicht übergangen werden)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:105
msgctxt "@label"
msgid "Change print core %1 from %2 to %3."
msgstr "Print Core %1 von %2 auf %3 wechseln."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:108
msgctxt "@label"
msgid "Change build plate to %1 (This cannot be overridden)."
msgstr "Druckplatte auf %1 wechseln (Dies kann nicht übergangen werden)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:94
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:115
msgctxt "@label"
msgid "Override will use the specified settings with the existing printer configuration. This may result in a failed print."
-msgstr ""
+msgstr "Überschreiben verwendet die definierten Einstellungen mit der vorhandenen Druckerkonfiguration. Dies kann zu einem fehlgeschlagenen Druck führen."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:135
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:156
msgctxt "@label"
msgid "Aluminum"
msgstr "Aluminium"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:75
-msgctxt "@info:tooltip"
-msgid "Connect to a printer"
-msgstr "Mit einem Drucker verbinden"
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:92
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:100
msgctxt "@info"
msgid ""
"Please make sure your printer has a connection:\n"
"- Check if the printer is turned on.\n"
-"- Check if the printer is connected to the network."
+"- Check if the printer is connected to the network.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
+"Stellen Sie sicher, dass der Drucker verbunden ist:\n"
+"– Prüfen Sie, ob der Drucker eingeschaltet ist.– Prüfen Sie, ob der Drucker mit dem Netzwerk verbunden ist.\n"
+"– Prüfen Sie, ob Sie angemeldet sind, falls Sie über die Cloud verbundene Drucker suchen möchten."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:110
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
msgctxt "@info"
-msgid "Please select a network connected printer to monitor."
-msgstr ""
+msgid "Please connect your printer to the network."
+msgstr "Verbinden Sie Ihren Drucker bitte mit dem Netzwerk."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:126
-msgctxt "@info"
-msgid "Please connect your Ultimaker printer to your local network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:165
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
msgctxt "@label link to technical assistance"
msgid "View user manuals online"
-msgstr ""
+msgstr "Benutzerhandbücher online anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:18
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:47
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr "Farbschema"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:105
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Materialfarbe"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:109
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Linientyp"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:113
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Vorschub"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:117
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Schichtdicke"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:154
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Kompatibilitätsmodus"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:229
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
msgid "Travels"
-msgstr ""
+msgstr "Bewegungen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:235
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
msgid "Helpers"
-msgstr ""
+msgstr "Helfer"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:241
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
msgid "Shell"
-msgstr ""
+msgstr "Gehäuse"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:247
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
msgid "Infill"
msgstr "Füllung"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Nur obere Schichten anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:307
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:308
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr "5 detaillierte Schichten oben anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Oben/Unten"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:325
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Innenwand"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:432
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -2503,30 +2356,25 @@ msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Aktive Skripts Nachbearbeitung ändern"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:16
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:17
msgctxt "@title:window"
msgid "More information on anonymous data collection"
msgstr "Weitere Informationen zur anonymen Datenerfassung"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:66
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:74
msgctxt "@text:window"
-msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
-msgstr "Cura sendet anonyme Daten an Ultimaker, um die Druckqualität und Benutzererfahrung zu steigern. Nachfolgend ist ein Beispiel aller Daten, die gesendet werden."
+msgid "Ultimaker Cura collects anonymous data in order to improve the print quality and user experience. Below is an example of all the data that is shared:"
+msgstr "Ultimaker Cura erfasst anonyme Daten, um die Druckqualität und Benutzererfahrung zu steigern. Nachfolgend ist ein Beispiel aller Daten, die geteilt werden:"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:101
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:109
msgctxt "@text:window"
-msgid "I don't want to send this data"
-msgstr ""
+msgid "I don't want to send anonymous data"
+msgstr "Ich möchte keine anonymen Daten senden"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:111
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:118
msgctxt "@text:window"
-msgid "Allow sending this data to Ultimaker and help us improve Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/R2D2/EvaluationSidebar.qml:49
-msgctxt "@label"
-msgid "No print selected"
-msgstr ""
+msgid "Allow sending anonymous data"
+msgstr "Senden von anonymen Daten erlauben"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
msgctxt "@title:window"
@@ -2575,19 +2423,19 @@ msgstr "Tiefe (mm)"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:126
msgctxt "@info:tooltip"
-msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
-msgstr "Standardmäßig repräsentieren weiße Pixel hohe Punkte im Netz und schwarze Pixel repräsentieren niedrige Punkte im Netz. Ändern Sie diese Option um das Verhalten so umzukehren, dass schwarze Pixel hohe Punkte im Netz darstellen und weiße Pixel niedrige Punkte im Netz."
-
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
-msgctxt "@item:inlistbox"
-msgid "Lighter is higher"
-msgstr "Heller ist höher"
+msgid "For lithophanes dark pixels should correspond to thicker locations in order to block more light coming through. For height maps lighter pixels signify higher terrain, so lighter pixels should correspond to thicker locations in the generated 3D model."
+msgstr "Für Lithophanien sollten dunkle Pixel dickeren Positionen entsprechen, um mehr einfallendes Licht zu blockieren. Für Höhenkarten stellen hellere Pixel höheres Terrain dar, sodass hellere Pixel dickeren Positionen im generierten 3D-Modell entsprechen sollten."
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
msgctxt "@item:inlistbox"
msgid "Darker is higher"
msgstr "Dunkler ist höher"
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
+msgctxt "@item:inlistbox"
+msgid "Lighter is higher"
+msgstr "Heller ist höher"
+
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:149
msgctxt "@info:tooltip"
msgid "The amount of smoothing to apply to the image."
@@ -2598,70 +2446,69 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Glättung"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:37
-msgctxt "@label"
-msgid "Mesh Type"
-msgstr "Mesh-Typ"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:68
-msgctxt "@label"
-msgid "Normal model"
-msgstr "Normales Modell"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:75
-msgctxt "@label"
-msgid "Print as support"
-msgstr "Als Stützstruktur drucken"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:83
-msgctxt "@label"
-msgid "Don't support overlap with other models"
-msgstr "Keine Überlappung mit anderen Modellen unterstützen"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:91
-msgctxt "@label"
-msgid "Modify settings for overlap with other models"
-msgstr "Einstellungen für Überlappung mit anderen Modellen bearbeiten"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:99
-msgctxt "@label"
-msgid "Modify settings for infill of other models"
-msgstr "Einstellungen für Füllung von anderen Modellen bearbeiten"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
-msgctxt "@action:button"
-msgid "Select settings"
-msgstr "Einstellungen wählen"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:13
msgctxt "@title:window"
msgid "Select Settings to Customize for this model"
msgstr "Einstellungen für die benutzerdefinierte Anpassung dieses Modells wählen"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:431
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:56
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtern..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:445
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:70
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Alle anzeigen"
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:44
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Mesh-Typ"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:85
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Normales Modell"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:97
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Als Stützstruktur drucken"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:109
+msgctxt "@label"
+msgid "Modify settings for overlaps"
+msgstr "Einstellungen für Überlappungen ändern"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:121
+msgctxt "@label"
+msgid "Don't support overlaps"
+msgstr "Überlappungen nicht unterstützen"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:145
+msgctxt "@action:checkbox"
+msgid "Infill only"
+msgstr "Nur Füllungen"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:368
+msgctxt "@action:button"
+msgid "Select settings"
+msgstr "Einstellungen wählen"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:14
msgctxt "@title:window"
msgid "Open Project"
msgstr "Projekt öffnen"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:58
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Update/override existing profile"
msgid "Update existing"
msgstr "Vorhandenes aktualisieren"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:59
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Save settings in a new profile"
msgid "Create new"
msgstr "Neu erstellen"
@@ -2688,6 +2535,11 @@ msgctxt "@action:ComboBox option"
msgid "Update"
msgstr "Aktualisierung"
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
+msgctxt "@action:ComboBox option"
+msgid "Create new"
+msgstr "Neu erstellen"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
@@ -2701,7 +2553,7 @@ msgid "Printer Group"
msgstr "Druckergruppe"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:220
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Profileinstellungen"
@@ -2712,75 +2564,81 @@ msgid "How should the conflict in the profile be resolved?"
msgstr "Wie soll der Konflikt im Profil gelöst werden?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:323
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:221
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:244
msgctxt "@action:label"
msgid "Name"
msgstr "Name"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:261
+msgctxt "@action:label"
+msgid "Intent"
+msgstr "Intent"
+
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:228
msgctxt "@action:label"
msgid "Not in profile"
msgstr "Nicht im Profil"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:210
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:233
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
msgstr[0] "%1 überschreiben"
msgstr[1] "%1 überschreibt"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:247
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:262
msgctxt "@action:label"
msgid "Derivative from"
msgstr "Ableitung von"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:252
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:267
msgctxt "@action:label"
msgid "%1, %2 override"
msgid_plural "%1, %2 overrides"
msgstr[0] "%1, %2 überschreiben"
msgstr[1] "%1, %2 überschreibt"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:268
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:283
msgctxt "@action:label"
msgid "Material settings"
msgstr "Materialeinstellungen"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:284
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:299
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
msgstr "Wie soll der Konflikt im Material gelöst werden?"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:342
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Sichtbarkeit einstellen"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:336
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:351
msgctxt "@action:label"
msgid "Mode"
msgstr "Modus"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:367
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Sichtbare Einstellungen:"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:372
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 von %2"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:383
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:398
msgctxt "@action:warning"
msgid "Loading a project will clear all models on the build plate."
msgstr "Das Laden eines Projekts entfernt alle Modelle von der Druckplatte."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:401
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:416
msgctxt "@action:button"
msgid "Open"
msgstr "Öffnen"
@@ -2788,285 +2646,140 @@ msgstr "Öffnen"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
msgctxt "@title"
msgid "My Backups"
-msgstr ""
+msgstr "Meine Backups"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:38
msgctxt "@empty_state"
msgid "You don't have any backups currently. Use the 'Backup Now' button to create one."
-msgstr ""
+msgstr "Sie verfügen derzeit über keine Backups. Verwenden Sie die Schaltfläche ‚Jetzt Backup erstellen‘, um ein Backup zu erstellen."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:60
msgctxt "@backup_limit_info"
msgid "During the preview phase, you'll be limited to 5 visible backups. Remove a backup to see older ones."
-msgstr ""
+msgstr "In der Vorschau-Phase sind Sie auf 5 sichtbare Backups beschränkt. Ein Backup entfernen, um ältere anzusehen."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:34
msgctxt "@description"
msgid "Backup and synchronize your Cura settings."
-msgstr ""
+msgstr "Ihre Cura-Einstellungen sichern und synchronisieren."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:51
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:138
msgctxt "@button"
msgid "Sign in"
-msgstr ""
+msgstr "Anmelden"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
msgctxt "@title:window"
msgid "Cura Backups"
-msgstr ""
+msgstr "Cura-Backups"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
msgctxt "@backuplist:label"
msgid "Cura Version"
-msgstr ""
+msgstr "Cura-Version"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
msgctxt "@backuplist:label"
msgid "Machines"
-msgstr ""
+msgstr "Maschinen"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
msgctxt "@backuplist:label"
msgid "Materials"
-msgstr ""
+msgstr "Materialien"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
msgctxt "@backuplist:label"
msgid "Profiles"
-msgstr ""
+msgstr "Profile"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
msgctxt "@backuplist:label"
msgid "Plugins"
-msgstr ""
+msgstr "Plugins"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
msgctxt "@button"
msgid "Restore"
-msgstr ""
+msgstr "Wiederherstellen"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
msgctxt "@dialog:title"
msgid "Delete Backup"
-msgstr ""
+msgstr "Backup löschen"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:100
msgctxt "@dialog:info"
msgid "Are you sure you want to delete this backup? This cannot be undone."
-msgstr ""
+msgstr "Soll dieses Backup wirklich gelöscht werden? Der Vorgang kann nicht rückgängig gemacht werden."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:108
msgctxt "@dialog:title"
msgid "Restore Backup"
-msgstr ""
+msgstr "Backup wiederherstellen"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:109
msgctxt "@dialog:info"
msgid "You will need to restart Cura before your backup is restored. Do you want to close Cura now?"
-msgstr ""
+msgstr "Cura muss neu gestartet werden, um Ihre Datensicherung wiederherzustellen. Möchten Sie Cura jetzt schließen?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:22
msgctxt "@button"
msgid "Want more?"
-msgstr ""
+msgstr "Möchten Sie mehr?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
msgctxt "@button"
msgid "Backup Now"
-msgstr ""
+msgstr "Jetzt Backup durchführen"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
msgctxt "@checkbox:description"
msgid "Auto Backup"
-msgstr ""
+msgstr "Automatisches Backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:44
msgctxt "@checkbox:description"
msgid "Automatically create a backup each day that Cura is started."
-msgstr ""
+msgstr "An jedem Tag, an dem Cura gestartet wird, ein automatisches Backup erstellen."
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMainSettingsSelector.qml:75
-msgctxt "@label"
-msgid "Not supported"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:35
-msgctxt "@action:button"
-msgid "Previous"
-msgstr "Zurück"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
-msgctxt "@action:button"
-msgid "Export"
-msgstr "Export"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Weiter"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:169
-msgctxt "@label"
-msgid "Tip"
-msgstr "Tipp"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:160
-msgctxt "@label"
-msgid "Print experiment"
-msgstr "Druckexperiment"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageValidation.qml:25
-msgctxt "@label"
-msgid "Checklist"
-msgstr "Checkliste"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:26
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:25
-msgctxt "@title"
-msgid "Select Printer Upgrades"
-msgstr "Drucker-Upgrades wählen"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:38
-msgctxt "@label"
-msgid "Please select any upgrades made to this Ultimaker 2."
-msgstr "Wählen Sie bitte alle durchgeführten Upgrades für diesen Ultimaker 2."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
-msgctxt "@label"
-msgid "Olsson Block"
-msgstr "Olsson-Block"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:30
msgctxt "@title"
msgid "Build Plate Leveling"
msgstr "Nivellierung der Druckplatte"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:38
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:44
msgctxt "@label"
msgid "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted."
msgstr "Um sicherzustellen, dass Ihre Drucke hervorragend werden, können Sie nun Ihre Druckplatte justieren. Wenn Sie auf „Gehe zur nächsten Position“ klicken, bewegt sich die Düse zu den verschiedenen Positionen, die justiert werden können."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:57
msgctxt "@label"
msgid "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle."
msgstr "Legen Sie für jede Position ein Blatt Papier unter die Düse und stellen Sie die Höhe der Druckplatte ein. Die Höhe der Druckplatte ist korrekt, wenn das Papier von der Spitze der Düse leicht berührt wird."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:62
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:75
msgctxt "@action:button"
msgid "Start Build Plate Leveling"
msgstr "Nivellierung der Druckplatte starten"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:74
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:87
msgctxt "@action:button"
msgid "Move to Next Position"
msgstr "Gehe zur nächsten Position"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:37
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker Original"
msgstr "Wählen Sie bitte alle Upgrades für dieses Ultimaker-Original"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:45
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:41
msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Beheizte Druckplatte (offizielles Kit oder Eigenbau)"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
-msgctxt "@title"
-msgid "Check Printer"
-msgstr "Drucker prüfen"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
-msgctxt "@label"
-msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
-msgstr "Sie sollten einige Sanity Checks bei Ihrem Ultimaker durchführen. Sie können diesen Schritt überspringen, wenn Sie wissen, dass Ihr Gerät funktionsfähig ist"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
-msgctxt "@action:button"
-msgid "Start Printer Check"
-msgstr "Überprüfung des Druckers starten"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
-msgctxt "@label"
-msgid "Connection: "
-msgstr "Verbindung: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Connected"
-msgstr "Verbunden"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Not connected"
-msgstr "Nicht verbunden"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
-msgctxt "@label"
-msgid "Min endstop X: "
-msgstr "Min. Endstopp X: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-msgctxt "@info:status"
-msgid "Works"
-msgstr "Funktionsfähig"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Not checked"
-msgstr "Nicht überprüft"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
-msgctxt "@label"
-msgid "Min endstop Y: "
-msgstr "Min. Endstopp Y: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
-msgctxt "@label"
-msgid "Min endstop Z: "
-msgstr "Min. Endstopp Z: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
-msgctxt "@label"
-msgid "Nozzle temperature check: "
-msgstr "Temperaturprüfung der Düse: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Stop Heating"
-msgstr "Aufheizen stoppen"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Start Heating"
-msgstr "Aufheizen starten"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
-msgctxt "@label"
-msgid "Build plate temperature check:"
-msgstr "Temperaturprüfung der Druckplatte:"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Checked"
-msgstr "Geprüft"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
-msgctxt "@label"
-msgid "Everything is in order! You're done with your CheckUp."
-msgstr "Alles ist in Ordnung! Der Check-up ist abgeschlossen."
-
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
@@ -3117,170 +2830,176 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Soll das Drucken wirklich abgebrochen werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
msgctxt "@title"
msgid "Information"
msgstr "Informationen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
msgctxt "@title:window"
msgid "Confirm Diameter Change"
msgstr "Änderung Durchmesser bestätigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:102
msgctxt "@label (%1 is a number)"
msgid "The new filament diameter is set to %1 mm, which is not compatible with the current extruder. Do you wish to continue?"
msgstr "Der neue Filament-Durchmesser wurde auf %1 mm eingestellt, was nicht kompatibel mit dem aktuellen Extruder ist. Möchten Sie fortfahren?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:128
msgctxt "@label"
msgid "Display Name"
msgstr "Namen anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:138
msgctxt "@label"
msgid "Brand"
msgstr "Marke"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:148
msgctxt "@label"
msgid "Material Type"
msgstr "Materialtyp"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:158
msgctxt "@label"
msgid "Color"
msgstr "Farbe"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:208
msgctxt "@label"
msgid "Properties"
msgstr "Eigenschaften"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:214
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:210
msgctxt "@label"
msgid "Density"
msgstr "Dichte"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:229
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:225
msgctxt "@label"
msgid "Diameter"
msgstr "Durchmesser"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:259
msgctxt "@label"
msgid "Filament Cost"
msgstr "Filamentkosten"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:276
msgctxt "@label"
msgid "Filament weight"
msgstr "Filamentgewicht"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:294
msgctxt "@label"
msgid "Filament length"
msgstr "Filamentlänge"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:307
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:303
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Kosten pro Meter"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:317
msgctxt "@label"
msgid "This material is linked to %1 and shares some of its properties."
msgstr "Dieses Material ist mit %1 verknüpft und teilt sich damit einige seiner Eigenschaften."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:324
msgctxt "@label"
msgid "Unlink Material"
msgstr "Material trennen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:339
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:335
msgctxt "@label"
msgid "Description"
msgstr "Beschreibung"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:352
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:348
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Haftungsinformationen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:17
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
msgctxt "@label"
msgid "Print settings"
msgstr "Druckeinstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:84
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:84
msgctxt "@action:button"
msgid "Activate"
msgstr "Aktivieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:126
msgctxt "@action:button"
msgid "Create"
msgstr "Erstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:140
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Duplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:141
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:167
msgctxt "@action:button"
msgid "Import"
msgstr "Import"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:203
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:179
+msgctxt "@action:button"
+msgid "Export"
+msgstr "Export"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:233
msgctxt "@action:label"
msgid "Printer"
msgstr "Drucker"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:262
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:274
msgctxt "@title:window"
msgid "Confirm Remove"
msgstr "Entfernen bestätigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:263
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:247
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:300
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:275
msgctxt "@label (%1 is object name)"
msgid "Are you sure you wish to remove %1? This cannot be undone!"
msgstr "Möchten Sie %1 wirklich entfernen? Dies kann nicht rückgängig gemacht werden!"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:277
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:285
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:322
msgctxt "@title:window"
msgid "Import Material"
msgstr "Material importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:323
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Could not import material %1: %2"
msgstr "Material konnte nicht importiert werden %1: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:327
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully imported material %1"
msgstr "Material wurde erfolgreich importiert %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:316
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:345
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:353
msgctxt "@title:window"
msgid "Export Material"
msgstr "Material exportieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:357
msgctxt "@info:status Don't translate the XML tags and !"
msgid "Failed to export material to %1: %2"
msgstr "Exportieren des Materials nach %1: %2 schlug fehl"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:363
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Material erfolgreich nach %1 exportiert"
@@ -3295,415 +3014,425 @@ msgctxt "@label:textbox"
msgid "Check all"
msgstr "Alle prüfen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:47
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:61
msgctxt "@info:status"
msgid "Calculated"
msgstr "Berechnet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:75
msgctxt "@title:column"
msgid "Setting"
msgstr "Einstellung"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
msgctxt "@title:column"
msgid "Profile"
msgstr "Profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:74
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:89
msgctxt "@title:column"
msgid "Current"
msgstr "Aktuell"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:97
msgctxt "@title:column"
msgid "Unit"
msgstr "Einheit"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr "Allgemein"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:126
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:132
msgctxt "@label"
msgid "Interface"
msgstr "Schnittstelle"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:143
msgctxt "@label"
msgid "Language:"
msgstr "Sprache:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:210
msgctxt "@label"
msgid "Currency:"
msgstr "Währung:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:223
msgctxt "@label"
msgid "Theme:"
msgstr "Thema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:273
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:279
msgctxt "@label"
msgid "You will need to restart the application for these changes to have effect."
msgstr "Die Anwendung muss neu gestartet werden, um die Änderungen zu übernehmen."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:296
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Bei Änderung der Einstellungen automatisch schneiden."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Automatisch schneiden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:312
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Viewport-Verhalten"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
msgctxt "@info:tooltip"
msgid "Highlight unsupported areas of the model in red. Without support these areas will not print properly."
msgstr "Nicht gestützte Bereiche des Modells in rot hervorheben. Ohne Support werden diese Bereiche nicht korrekt gedruckt."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:335
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Überhang anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:343
msgctxt "@info:tooltip"
msgid "Moves the camera so the model is in the center of the view when a model is selected"
msgstr "Bewegt die Kamera, bis sich das Modell im Mittelpunkt der Ansicht befindet, wenn ein Modell ausgewählt wurde"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:348
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr "Zentrieren Sie die Kamera, wenn das Element ausgewählt wurde"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Soll das standardmäßige Zoom-Verhalten von Cura umgekehrt werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:355
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Kehren Sie die Richtung des Kamera-Zooms um."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr "Soll das Zoomen in Richtung der Maus erfolgen?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
+msgctxt "@info:tooltip"
+msgid "Zooming towards the mouse is not supported in the orthographic perspective."
+msgstr "Das Zoomen in Richtung der Maus wird in der orthografischen Perspektive nicht unterstützt."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "In Mausrichtung zoomen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:380
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:410
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved so that they no longer intersect?"
msgstr "Sollen Modelle auf der Plattform so verschoben werden, dass sie sich nicht länger überschneiden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:385
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr "Stellen Sie sicher, dass die Modelle getrennt gehalten werden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:394
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:424
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved down to touch the build plate?"
msgstr "Sollen Modelle auf der Plattform so nach unten verschoben werden, dass sie die Druckplatte berühren?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:429
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr "Setzt Modelle automatisch auf der Druckplatte ab"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:411
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr "Warnmeldung im G-Code-Reader anzeigen."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr "Warnmeldung in G-Code-Reader"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:428
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:458
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "Soll die Schicht in den Kompatibilitätsmodus gezwungen werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:463
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr "Schichtenansicht Kompatibilitätsmodus erzwingen (Neustart erforderlich)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
+msgctxt "@info:tooltip"
+msgid "Should Cura open at the location it was closed?"
+msgstr "Sollte Cura sich an der Stelle öffnen, an der das Programm geschlossen wurde?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
+msgctxt "@option:check"
+msgid "Restore window position on start"
+msgstr "Fensterposition beim Start wiederherstellen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:488
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr "Welches Kamera-Rendering sollte verwendet werden?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:495
+msgctxt "@window:text"
+msgid "Camera rendering:"
+msgstr "Kamera-Rendering:"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+msgid "Perspective"
+msgstr "Ansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+msgid "Orthographic"
+msgstr "Orthogonal"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Dateien öffnen und speichern"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:456
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:545
msgctxt "@info:tooltip"
msgid "Should models be scaled to the build volume if they are too large?"
msgstr "Sollen Modelle an das Erstellungsvolumen angepasst werden, wenn sie zu groß sind?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:461
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:550
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Große Modelle anpassen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:560
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Ein Modell kann extrem klein erscheinen, wenn seine Maßeinheit z. B. in Metern anstelle von Millimetern angegeben ist. Sollen diese Modelle hoch skaliert werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:565
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Extrem kleine Modelle skalieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr "Sollten Modelle gewählt werden, nachdem sie geladen wurden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:491
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:580
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr "Modelle wählen, nachdem sie geladen wurden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
msgctxt "@info:tooltip"
msgid "Should a prefix based on the printer name be added to the print job name automatically?"
msgstr "Soll ein Präfix anhand des Druckernamens automatisch zum Namen des Druckauftrags hinzugefügt werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr "Geräte-Präfix zu Auftragsnamen hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:516
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:605
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr "Soll beim Speichern einer Projektdatei eine Zusammenfassung angezeigt werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:609
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr "Dialog Zusammenfassung beim Speichern eines Projekts anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Standardverhalten beim Öffnen einer Projektdatei"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:627
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Standardverhalten beim Öffnen einer Projektdatei: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Stets nachfragen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:642
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Immer als Projekt öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:554
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Modelle immer importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:679
msgctxt "@info:tooltip"
msgid "When you have made changes to a profile and switched to a different one, a dialog will be shown asking whether you want to keep your modifications or not, or you can choose a default behaviour and never show that dialog again."
msgstr "Wenn Sie Änderungen für ein Profil vorgenommen haben und zu einem anderen Profil gewechselt sind, wird ein Dialog angezeigt, der hinterfragt, ob Sie Ihre Änderungen beibehalten möchten oder nicht; optional können Sie ein Standardverhalten wählen, sodass dieser Dialog nicht erneut angezeigt wird."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:599
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:52
msgctxt "@label"
msgid "Profiles"
msgstr "Profile"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:693
msgctxt "@window:text"
msgid "Default behavior for changed setting values when switching to a different profile: "
msgstr "Standardverhalten für geänderte Einstellungswerte beim Wechsel zu einem anderen Profil: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:707
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:157
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Stets nachfragen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Geänderte Einstellungen immer verwerfen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:709
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr "Geänderte Einstellungen immer auf neues Profil übertragen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:654
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
msgctxt "@label"
msgid "Privacy"
msgstr "Privatsphäre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:661
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:750
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr "Soll Cura bei Programmstart nach Updates suchen?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:666
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:755
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Bei Start nach Updates suchen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:676
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:765
msgctxt "@info:tooltip"
msgid "Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored."
msgstr "Sollen anonyme Daten über Ihren Druck an Ultimaker gesendet werden? Beachten Sie, dass keine Modelle, IP-Adressen oder andere personenbezogene Daten gesendet oder gespeichert werden."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:681
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:770
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "(Anonyme) Druckinformationen senden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:690
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:779
msgctxt "@action:button"
msgid "More information"
msgstr "Mehr Informationen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
-msgctxt "@label"
-msgid "Experimental"
-msgstr "Experimentell"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:715
-msgctxt "@info:tooltip"
-msgid "Use multi build plate functionality"
-msgstr "Mehrfach-Druckplattenfunktion verwenden"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
-msgctxt "@option:check"
-msgid "Use multi build plate functionality (restart required)"
-msgstr "Mehrfach-Druckplattenfunktion verwenden (Neustart erforderlich)"
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:16
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr "Drucker"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:57
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:63
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
msgctxt "@action:button"
msgid "Rename"
msgstr "Umbenennen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:363
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:419
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profile"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:104
msgctxt "@label"
msgid "Create"
msgstr "Erstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@label"
msgid "Duplicate"
msgstr "Duplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:202
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Profil erstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:176
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:204
msgctxt "@info"
msgid "Please provide a name for this profile."
-msgstr ""
+msgstr "Geben Sie bitte einen Namen für dieses Profil an."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:260
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Profil duplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:291
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Profil umbenennen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:276
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:304
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Profil importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:333
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Profil exportieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:396
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Drucker: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Default profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Custom profiles"
-msgstr "Benutzerdefinierte Profile"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:554
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr "Profil mit aktuellen Einstellungen/Überschreibungen aktualisieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:561
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:257
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Aktuelle Änderungen verwerfen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:514
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:580
msgctxt "@action:label"
msgid "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below."
msgstr "Dieses Profil verwendet die vom Drucker festgelegten Standardeinstellungen, deshalb sind in der folgenden Liste keine Einstellungen/Überschreibungen enthalten."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:521
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:588
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr "Ihre aktuellen Einstellungen stimmen mit dem gewählten Profil überein."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:606
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Globale Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:90
msgctxt "@action:button"
msgid "Marketplace"
-msgstr ""
+msgstr "Marktplatz"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
@@ -3726,7 +3455,7 @@ msgstr "&Ansicht"
#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
msgctxt "@title:menu menubar:toplevel"
msgid "&Settings"
-msgstr ""
+msgstr "&Einstellungen"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
msgctxt "@title:menu menubar:toplevel"
@@ -3743,12 +3472,12 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Hilfe"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
msgctxt "@title:window"
msgid "New project"
msgstr "Neues Projekt"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:125
msgctxt "@info:question"
msgid "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings."
msgstr "Möchten Sie wirklich ein neues Projekt beginnen? Damit werden das Druckbett und alle nicht gespeicherten Einstellungen gelöscht."
@@ -3760,36 +3489,36 @@ msgstr "Unbenannt"
#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "search settings"
-msgstr ""
+msgid "Search settings"
+msgstr "Einstellungen durchsuchen"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:462
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Werte für alle Extruder kopieren"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:474
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:471
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr "Alle geänderten Werte für alle Extruder kopieren"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Diese Einstellung ausblenden"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:521
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Diese Einstellung ausblenden"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Diese Einstellung weiterhin anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:557
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Sichtbarkeit einstellen wird konfiguriert..."
@@ -3805,27 +3534,32 @@ msgstr ""
"\n"
"Klicken Sie, um diese Einstellungen sichtbar zu machen."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:81
+msgctxt "@label"
+msgid "This setting is not used because all the settings that it influences are overridden."
+msgstr "Diese Einstellung wird nicht verwendet, weil alle hierdurch beeinflussten Einstellungen aufgehoben werden."
+
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:86
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Hat Einfluss auf"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:91
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Wird beeinflusst von"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:166
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:187
msgctxt "@label"
msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders."
msgstr "Diese Einstellung wird stets zwischen allen Extrudern geteilt. Eine Änderung ändert den Wert für alle Extruder."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:191
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr "Der Wert wird von Pro-Extruder-Werten gelöst "
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:230
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3836,7 +3570,7 @@ msgstr ""
"\n"
"Klicken Sie, um den Wert des Profils wiederherzustellen."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:329
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3847,87 +3581,79 @@ msgstr ""
"\n"
"Klicken Sie, um den berechneten Wert wiederherzustellen."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/NoIntentIcon.qml:31
+msgctxt "@label %1 is filled in with the type of a profile. %2 is filled with a list of numbers (eg '1' or '1, 2')"
+msgid "There is no %1 profile for the configuration in extruder %2. The default intent will be used instead"
+msgid_plural "There is no %1 profile for the configurations in extruders %2. The default intent will be used instead"
+msgstr[0] ""
+msgstr[1] ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
msgctxt "@button"
msgid "Recommended"
-msgstr ""
+msgstr "Empfohlen"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
msgctxt "@button"
msgid "Custom"
-msgstr ""
+msgstr "Benutzerdefiniert"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
msgctxt "@label"
msgid "Gradual infill"
-msgstr ""
+msgstr "Stufenweise Füllung"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:232
msgctxt "@label"
msgid "Gradual infill will gradually increase the amount of infill towards the top."
msgstr "Die graduelle Füllung steigert die Menge der Füllung nach oben hin schrittweise."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:29
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:30
msgctxt "@label"
msgid "Support"
-msgstr ""
+msgstr "Stützstruktur"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:71
msgctxt "@label"
msgid "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."
msgstr "Damit werden Strukturen zur Unterstützung von Modellteilen mit Überhängen generiert. Ohne diese Strukturen würden solche Teile während des Druckvorgangs zusammenfallen."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:136
-msgctxt "@label"
-msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
-msgstr "Wählen Sie, welcher Extruder für die Unterstützung verwendet wird. Dient zum Konstruieren von Stützstrukturen unter dem Modell, damit dieses nicht absinkt oder frei schwebend gedruckt wird."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:29
msgctxt "@label"
msgid "Adhesion"
-msgstr ""
+msgstr "Haftung"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:74
msgctxt "@label"
msgid "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."
msgstr "Drucken eines Brim- oder Raft-Elements aktivieren. Es wird ein flacher Bereich rund um oder unter Ihrem Objekt hinzugefügt, das im Anschluss leicht abgeschnitten werden kann."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:175
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Schichtdicke"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:206
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:81
msgctxt "@tooltip"
msgid "You have modified some profile settings. If you want to change these go to custom mode."
msgstr "Sie haben einige Profileinstellungen geändert. Wenn Sie diese ändern möchten, wechseln Sie in den Modus „Benutzerdefiniert“."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:355
-msgctxt "@tooltip"
-msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:449
-msgctxt "@tooltip"
-msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
-msgstr "Ein benutzerdefiniertes Profil ist derzeit aktiv. Wählen Sie ein voreingestelltes Qualitätsprofil aus der Registerkarte „Benutzerdefiniert“, um den Schieberegler für Qualität zu aktivieren"
-
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:13
msgctxt "@label:Should be short"
msgid "On"
-msgstr ""
+msgstr "Ein"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
msgctxt "@label:Should be short"
msgid "Off"
-msgstr ""
+msgstr "Aus"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:33
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Experimentell"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:47
msgctxt "@label"
msgid "Profile"
-msgstr ""
+msgstr "Profil"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:172
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3938,10 +3664,15 @@ msgstr ""
"\n"
"Klicken Sie, um den Profilmanager zu öffnen."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:160
+msgctxt "@label:header"
+msgid "Custom profiles"
+msgstr "Benutzerdefinierte Profile"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:21
msgctxt "@label shown when we load a Gcode file"
-msgid "Print setup disabled. G code file can not be modified."
-msgstr ""
+msgid "Print setup disabled. G-code file can not be modified."
+msgstr "Druckeinrichtung ist deaktiviert. G-Code-Datei kann nicht geändert werden."
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
@@ -3973,59 +3704,59 @@ msgctxt "@label"
msgid "Send G-code"
msgstr "G-Code senden"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:364
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:365
msgctxt "@tooltip of G-code command input"
msgid "Send a custom G-code command to the connected printer. Press 'enter' to send the command."
msgstr "Einen benutzerdefinierten G-Code-Befehl an den verbundenen Drucker senden. „Eingabe“ drücken, um den Befehl zu senden."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:41
msgctxt "@label"
msgid "Extruder"
msgstr "Extruder"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:71
msgctxt "@tooltip"
msgid "The target temperature of the hotend. The hotend will heat up or cool down towards this temperature. If this is 0, the hotend heating is turned off."
msgstr "Die Zieltemperatur des Hotend. Das Hotend wird auf diese Temperatur aufgeheizt oder abgekühlt. Wenn der Wert 0 beträgt, wird die Hotend-Heizung ausgeschaltet."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:103
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr "Die aktuelle Temperatur dieses Hotends."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:177
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr "Die Temperatur, auf die das Hotend vorgeheizt wird."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:332
msgctxt "@button Cancel pre-heating"
msgid "Cancel"
msgstr "Abbrechen"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:344
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:335
msgctxt "@button"
msgid "Pre-heat"
msgstr "Vorheizen"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:370
msgctxt "@tooltip of pre-heat"
msgid "Heat the hotend in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the hotend to heat up when you're ready to print."
msgstr "Heizen Sie das Hotend vor Druckbeginn auf. Sie können Ihren Druck während des Aufheizens weiter anpassen und müssen nicht warten, bis das Hotend aufgeheizt ist, wenn Sie druckbereit sind."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:406
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr "Die Farbe des Materials in diesem Extruder."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:438
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Das Material in diesem Extruder."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:470
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Die in diesem Extruder eingesetzte Düse."
@@ -4065,12 +3796,12 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:46
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Favoriten"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:71
msgctxt "@label:category menu label"
msgid "Generic"
msgstr "Generisch"
@@ -4090,42 +3821,47 @@ msgctxt "@title:menu menubar:settings"
msgid "&Printer"
msgstr "Dr&ucker"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:26
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:27
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:36
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Als aktiven Extruder festlegen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Enable Extruder"
msgstr "Extruder aktivieren"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:49
msgctxt "@action:inmenu"
msgid "Disable Extruder"
msgstr "Extruder deaktivieren"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:62
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "&Druckplatte"
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:65
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profil"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:19
msgctxt "@action:inmenu menubar:view"
msgid "&Camera position"
msgstr "&Kameraposition"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:44
+msgctxt "@action:inmenu menubar:view"
+msgid "Camera view"
+msgstr "Kameraansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:47
+msgctxt "@action:inmenu menubar:view"
+msgid "Perspective"
+msgstr "Ansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:59
+msgctxt "@action:inmenu menubar:view"
+msgid "Orthographic"
+msgstr "Orthogonal"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:80
msgctxt "@action:inmenu menubar:view"
msgid "&Build plate"
msgstr "&Druckplatte"
@@ -4145,17 +3881,17 @@ msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Sichtbarkeit einstellen verwalten..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:33
msgctxt "@title:menu menubar:file"
msgid "&Save..."
msgstr "&Speichern..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:54
msgctxt "@title:menu menubar:file"
msgid "&Export..."
msgstr "&Exportieren..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:65
msgctxt "@action:inmenu menubar:file"
msgid "Export Selection..."
msgstr "Auswahl exportieren..."
@@ -4182,190 +3918,193 @@ msgstr "Anzahl Kopien"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
msgctxt "@header"
msgid "Configurations"
-msgstr ""
+msgstr "Konfigurationen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:112
msgctxt "@label"
msgid "Select configuration"
-msgstr ""
+msgstr "Konfiguration wählen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:201
-msgctxt "@label"
-msgid "See the material compatibility chart"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:274
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:223
msgctxt "@label"
msgid "Configurations"
-msgstr ""
+msgstr "Konfigurationen"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
msgctxt "@label"
msgid "Loading available configurations from the printer..."
-msgstr ""
+msgstr "Verfügbare Konfigurationen werden von diesem Drucker geladen..."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:58
msgctxt "@label"
msgid "The configurations are not available because the printer is disconnected."
-msgstr ""
+msgstr "Die Konfigurationen sind nicht verfügbar, da der Drucker getrennt ist."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:25
msgctxt "@header"
msgid "Custom"
-msgstr ""
+msgstr "Benutzerdefiniert"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
msgctxt "@label"
msgid "Printer"
-msgstr ""
+msgstr "Drucker"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:202
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
msgctxt "@label"
msgid "Enabled"
-msgstr ""
+msgstr "Aktiviert"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:251
msgctxt "@label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:344
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:378
msgctxt "@label"
msgid "Use glue for better adhesion with this material combination."
-msgstr ""
+msgstr "Für diese Materialkombination Kleber für eine bessere Haftung verwenden."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:128
msgctxt "@label"
msgid "This configuration is not available because %1 is not recognized. Please visit %2 to download the correct material profile."
-msgstr ""
+msgstr "Diese Konfigurationen sind nicht verfügbar, weil %1 nicht erkannt wird. Besuchen Sie bitte %2 für das Herunterladen des korrekten Materialprofils."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:129
msgctxt "@label"
msgid "Marketplace"
-msgstr ""
+msgstr "Marktplatz"
#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:15
msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr "&Zuletzt geöffnet"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr "Aktiver Druck"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr "Name des Auftrags"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Druckzeit"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:169
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr "Geschätzte verbleibende Zeit"
#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
msgctxt "@label"
-msgid "View types"
-msgstr ""
+msgid "View type"
+msgstr "Typ anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
msgctxt "@label"
-msgid "Hi "
-msgstr ""
+msgid "Object list"
+msgstr "Objektliste"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:22
+msgctxt "@label The argument is a username."
+msgid "Hi %1"
+msgstr "Hallo %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:33
msgctxt "@button"
msgid "Ultimaker account"
-msgstr ""
+msgstr "Ultimaker‑Konto"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
msgctxt "@button"
msgid "Sign out"
-msgstr ""
+msgstr "Abmelden"
#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
msgctxt "@action:button"
msgid "Sign in"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:29
-msgctxt "@label"
-msgid "Ultimaker Cloud"
-msgstr ""
+msgstr "Anmelden"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
msgctxt "@label"
msgid "The next generation 3D printing workflow"
-msgstr ""
+msgstr "Der 3D-Druckablauf der nächsten Generation"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:51
msgctxt "@text"
msgid ""
"- Send print jobs to Ultimaker printers outside your local network\n"
"- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
-"- Get exclusive access to material profiles from leading brands"
+"- Get exclusive access to print profiles from leading brands"
msgstr ""
+"- Aufträge an Ultimaker-Drucker außerhalb Ihres lokalen Netzwerks senden\n"
+"- Ihre Ultimaker Cura-Einstellungen für die Verwendung andernorts an die Cloud senden\n"
+"- Exklusiven Zugang zu Druckprofilen von führenden Marken erhalten"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
msgctxt "@button"
msgid "Create account"
-msgstr ""
+msgstr "Konto erstellen"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
msgctxt "@label"
msgid "No time estimation available"
-msgstr ""
+msgstr "Keine Zeitschätzung verfügbar"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:76
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
msgctxt "@label"
msgid "No cost estimation available"
-msgstr ""
+msgstr "Keine Kostenschätzung verfügbar"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
msgctxt "@button"
msgid "Preview"
-msgstr ""
+msgstr "Vorschau"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:55
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Das Slicing läuft..."
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:61
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:67
msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
+msgid "Unable to slice"
msgstr "Slicing nicht möglich"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:116
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
+msgctxt "@button"
+msgid "Processing"
+msgstr "Verarbeitung läuft"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
msgctxt "@button"
msgid "Slice"
-msgstr ""
+msgstr "Slice"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
msgctxt "@label"
msgid "Start the slicing process"
-msgstr ""
+msgstr "Slicing-Vorgang starten"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
msgctxt "@button"
msgid "Cancel"
-msgstr ""
+msgstr "Abbrechen"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
msgctxt "@label"
-msgid "Time specification"
-msgstr ""
+msgid "Time estimation"
+msgstr "Zeitschätzung"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
msgctxt "@label"
-msgid "Material specification"
-msgstr ""
+msgid "Material estimation"
+msgstr "Materialschätzung"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
msgctxt "@label m for meter"
@@ -4380,292 +4119,306 @@ msgstr "%1 g"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Connected printers"
-msgstr ""
+msgstr "Verbundene Drucker"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Preset printers"
-msgstr ""
+msgstr "Voreingestellte Drucker"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
msgctxt "@button"
msgid "Add printer"
-msgstr ""
+msgstr "Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:173
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
msgctxt "@button"
msgid "Manage printers"
-msgstr ""
+msgstr "Drucker verwalten"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
msgctxt "@action:inmenu"
msgid "Show Online Troubleshooting Guide"
-msgstr ""
+msgstr "Online-Fehlerbehebung anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr "Umschalten auf Vollbild-Modus"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
+msgctxt "@action:inmenu"
+msgid "Exit Full Screen"
+msgstr "Vollbildmodus beenden"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:103
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Rückgängig machen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:113
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "&Wiederholen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:123
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Beenden"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:131
msgctxt "@action:inmenu menubar:view"
msgid "3D View"
msgstr "3D-Ansicht"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:138
msgctxt "@action:inmenu menubar:view"
msgid "Front View"
msgstr "Vorderansicht"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:145
msgctxt "@action:inmenu menubar:view"
msgid "Top View"
msgstr "Draufsicht"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:152
msgctxt "@action:inmenu menubar:view"
msgid "Left Side View"
msgstr "Ansicht von links"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:159
msgctxt "@action:inmenu menubar:view"
msgid "Right Side View"
msgstr "Ansicht von rechts"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Cura konfigurieren..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:173
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Drucker hinzufügen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:179
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Dr&ucker verwalten..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Materialien werden verwaltet..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195
msgctxt "@action:inmenu menubar:profile"
msgid "&Update profile with current settings/overrides"
msgstr "&Profil mit aktuellen Einstellungen/Überschreibungen aktualisieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:192
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Aktuelle Änderungen verwerfen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr "P&rofil von aktuellen Einstellungen/Überschreibungen erstellen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Profile verwalten..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:229
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Online-&Dokumentation anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:237
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "&Fehler melden"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:245
+msgctxt "@action:inmenu menubar:help"
+msgid "What's New"
+msgstr "Neuheiten"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
msgctxt "@action:inmenu menubar:help"
msgid "About..."
msgstr "Über..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:258
msgctxt "@action:inmenu menubar:edit"
msgid "Delete Selected Model"
msgid_plural "Delete Selected Models"
msgstr[0] "Ausgewähltes Modell löschen"
msgstr[1] "Ausgewählte Modelle löschen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
msgctxt "@action:inmenu menubar:edit"
msgid "Center Selected Model"
msgid_plural "Center Selected Models"
msgstr[0] "Ausgewähltes Modell zentrieren"
msgstr[1] "Ausgewählte Modelle zentrieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
msgctxt "@action:inmenu menubar:edit"
msgid "Multiply Selected Model"
msgid_plural "Multiply Selected Models"
msgstr[0] "Ausgewähltes Modell multiplizieren"
msgstr[1] "Ausgewählte Modelle multiplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Modell löschen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:294
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Modell auf Druckplatte ze&ntrieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:283
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:300
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "Modelle &gruppieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:303
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:320
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Gruppierung für Modelle aufheben"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:313
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "Modelle &zusammenführen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "Modell &multiplizieren..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:347
msgctxt "@action:inmenu menubar:edit"
msgid "Select All Models"
msgstr "Alle Modelle wählen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:357
msgctxt "@action:inmenu menubar:edit"
msgid "Clear Build Plate"
msgstr "Druckplatte reinigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:367
msgctxt "@action:inmenu menubar:file"
msgid "Reload All Models"
msgstr "Alle Modelle neu laden"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:376
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models To All Build Plates"
msgstr "Alle Modelle an allen Druckplatten anordnen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:383
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Alle Modelle anordnen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:391
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Anordnung auswählen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:381
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:398
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr "Alle Modellpositionen zurücksetzen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:405
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Transformations"
msgstr "Alle Modelltransformationen zurücksetzen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:412
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Datei(en) öffnen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:420
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Neues Projekt..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:427
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Konfigurationsordner anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
msgid "&Marketplace"
-msgstr ""
+msgstr "&Marktplatz"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:181
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
msgctxt "@label"
msgid "This package will be installed after restarting."
msgstr "Dieses Paket wird nach einem Neustart installiert."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:538
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Cura wird geschlossen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:487
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:499
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:551
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr "Möchten Sie Cura wirklich beenden?"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:589
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:19
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Datei(en) öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:632
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:695
msgctxt "@window:title"
msgid "Install Package"
msgstr "Paket installieren"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:640
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:703
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Datei(en) öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:643
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:706
msgctxt "@text:window"
msgid "We have found one or more G-Code files within the files you have selected. You can only open one G-Code file at a time. If you want to open a G-Code file, please just select only one."
msgstr "Es wurden eine oder mehrere G-Code-Datei(en) innerhalb der von Ihnen gewählten Dateien gefunden. Sie können nur eine G-Code-Datei auf einmal öffnen. Wenn Sie eine G-Code-Datei öffnen möchten wählen Sie bitte nur eine Datei."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:713
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:18
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:809
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Drucker hinzufügen"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:817
+msgctxt "@title:window"
+msgid "What's New"
+msgstr "Neuheiten"
+
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
msgctxt "@label %1 is filled in with the name of an extruder"
msgid "Print Selected Model with %1"
@@ -4727,50 +4480,22 @@ msgctxt "@action:button"
msgid "Create New Profile"
msgstr "Neues Profil erstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:78
-msgctxt "@title:tab"
-msgid "Add a printer to Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:92
-msgctxt "@title:tab"
-msgid ""
-"Select the printer you want to use from the list below.\n"
-"\n"
-"If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:249
-msgctxt "@label"
-msgid "Manufacturer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:271
-msgctxt "@label"
-msgid "Printer Name"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:294
-msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Drucker hinzufügen"
-
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:15
msgctxt "@title:window"
msgid "About Cura"
msgstr "Über Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:56
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:57
msgctxt "@label"
msgid "version: %1"
msgstr "Version: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:72
msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing."
msgstr "Komplettlösung für den 3D-Druck mit geschmolzenem Filament."
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:85
msgctxt "@info:credit"
msgid ""
"Cura is developed by Ultimaker B.V. in cooperation with the community.\n"
@@ -4779,122 +4504,122 @@ msgstr ""
"Cura wurde von Ultimaker B.V. in Zusammenarbeit mit der Community entwickelt.\n"
"Cura verwendet mit Stolz die folgenden Open Source-Projekte:"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
msgctxt "@label"
msgid "Graphical user interface"
msgstr "Grafische Benutzerschnittstelle"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
msgctxt "@label"
msgid "Application framework"
msgstr "Anwendungsrahmenwerk"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
msgctxt "@label"
msgid "G-code generator"
msgstr "G-Code-Generator"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:138
msgctxt "@label"
msgid "Interprocess communication library"
msgstr "Bibliothek Interprozess-Kommunikation"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
msgctxt "@label"
msgid "Programming language"
msgstr "Programmiersprache"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
msgctxt "@label"
msgid "GUI framework"
msgstr "GUI-Rahmenwerk"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
msgctxt "@label"
msgid "GUI framework bindings"
msgstr "GUI-Rahmenwerk Einbindungen"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
msgctxt "@label"
msgid "C/C++ Binding library"
msgstr "C/C++ Einbindungsbibliothek"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
msgctxt "@label"
msgid "Data interchange format"
msgstr "Format Datenaustausch"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
msgctxt "@label"
msgid "Support library for scientific computing"
msgstr "Support-Bibliothek für wissenschaftliche Berechnung"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
msgctxt "@label"
msgid "Support library for faster math"
msgstr "Support-Bibliothek für schnelleres Rechnen"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
msgctxt "@label"
msgid "Support library for handling STL files"
msgstr "Support-Bibliothek für die Handhabung von STL-Dateien"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
msgctxt "@label"
msgid "Support library for handling planar objects"
msgstr "Support-Bibliothek für die Handhabung von ebenen Objekten"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
msgctxt "@label"
msgid "Support library for handling triangular meshes"
msgstr "Support-Bibliothek für die Handhabung von dreieckigen Netzen"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
msgctxt "@label"
msgid "Support library for analysis of complex networks"
msgstr "Support-Bibliothek für die Analyse von komplexen Netzwerken"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
msgctxt "@label"
msgid "Support library for handling 3MF files"
msgstr "Support-Bibliothek für die Handhabung von 3MF-Dateien"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
msgctxt "@label"
msgid "Support library for file metadata and streaming"
msgstr "Support-Bibliothek für Datei-Metadaten und Streaming"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
msgctxt "@label"
msgid "Serial communication library"
msgstr "Bibliothek für serielle Kommunikation"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
msgctxt "@label"
msgid "ZeroConf discovery library"
msgstr "Bibliothek für ZeroConf-Erkennung"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
msgctxt "@label"
msgid "Polygon clipping library"
msgstr "Bibliothek für Polygon-Beschneidung"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:156
msgctxt "@Label"
msgid "Python HTTP library"
msgstr "Bibliothek für Python HTTP"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
msgctxt "@label"
msgid "Font"
msgstr "Schriftart"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
msgctxt "@label"
msgid "SVG icons"
msgstr "SVG-Symbole"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:160
msgctxt "@label"
msgid "Linux cross-distribution application deployment"
msgstr "Distributionsunabhängiges Format für Linux-Anwendungen"
@@ -4914,27 +4639,27 @@ msgctxt "@title:window"
msgid "Save Project"
msgstr "Projekt speichern"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:138
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Druckplatte"
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:177
msgctxt "@action:label"
msgid "Extruder %1"
msgstr "Extruder %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:192
msgctxt "@action:label"
msgid "%1 & material"
msgstr "%1 & Material"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:243
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:194
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:label"
msgid "Don't show project summary on save again"
msgstr "Projektzusammenfassung beim Speichern nicht erneut anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:262
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:302
msgctxt "@action:button"
msgid "Save"
msgstr "Speichern"
@@ -4964,30 +4689,1451 @@ msgctxt "@action:button"
msgid "Import models"
msgstr "Modelle importieren"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:210
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Nur aktuelle Druckplatte anzeigen"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
+msgctxt "@label"
+msgid "Empty"
+msgstr "Leer"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:226
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "An allen Druckplatten ausrichten"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
+msgctxt "@label"
+msgid "Add a printer"
+msgstr "Einen Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:246
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "An aktueller Druckplatte ausrichten"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
+msgctxt "@label"
+msgid "Add a networked printer"
+msgstr "Einen vernetzten Drucker hinzufügen"
-#: X3GWriter/plugin.json
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
+msgctxt "@label"
+msgid "Add a non-networked printer"
+msgstr "Einen unvernetzten Drucker hinzufügen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:70
+msgctxt "@label"
+msgid "Add printer by IP address"
+msgstr "Drucker nach IP-Adresse hinzufügen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:133
+msgctxt "@text"
+msgid "Place enter your printer's IP address."
+msgstr "Bitte geben Sie die IP-Adresse Ihres Druckers ein."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:204
+msgctxt "@label"
+msgid "Could not connect to device."
+msgstr "Verbindung mit Drucker nicht möglich."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:208
+msgctxt "@label"
+msgid "The printer at this address has not responded yet."
+msgstr "Der Drucker unter dieser Adresse hat noch nicht reagiert."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:240
+msgctxt "@label"
+msgid "This printer cannot be added because it's an unknown printer or it's not the host of a group."
+msgstr "Dieser Drucker kann nicht hinzugefügt werden, weil es sich um einen unbekannten Drucker handelt oder er nicht im Host einer Gruppe enthalten ist."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:329
+msgctxt "@button"
+msgid "Back"
+msgstr "Zurück"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:342
+msgctxt "@button"
+msgid "Connect"
+msgstr "Verbinden"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/FirstStartMachineActionsContent.qml:77
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:123
+msgctxt "@button"
+msgid "Next"
+msgstr "Weiter"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:23
+msgctxt "@label"
+msgid "User Agreement"
+msgstr "Benutzervereinbarung"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:56
+msgctxt "@button"
+msgid "Agree"
+msgstr "Stimme zu"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:70
+msgctxt "@button"
+msgid "Decline and close"
+msgstr "Ablehnen und schließen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:24
+msgctxt "@label"
+msgid "Help us to improve Ultimaker Cura"
+msgstr "Helfen Sie uns, Ultimaker Cura zu verbessern"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:57
+msgctxt "@text"
+msgid "Ultimaker Cura collects anonymous data to improve print quality and user experience, including:"
+msgstr "Ultimaker Cura erfasst anonyme Daten, um die Druckqualität und Benutzererfahrung zu steigern. Dazu gehören:"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:71
+msgctxt "@text"
+msgid "Machine types"
+msgstr "Gerätetypen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:77
+msgctxt "@text"
+msgid "Material usage"
+msgstr "Materialverbrauch"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:83
+msgctxt "@text"
+msgid "Number of slices"
+msgstr "Anzahl der Slices"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:89
+msgctxt "@text"
+msgid "Print settings"
+msgstr "Druckeinstellungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:102
+msgctxt "@text"
+msgid "Data collected by Ultimaker Cura will not contain any personal information."
+msgstr "Die von Ultimaker Cura erfassten Daten enthalten keine personenbezogenen Daten."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:103
+msgctxt "@text"
+msgid "More information"
+msgstr "Mehr Informationen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WhatsNewContent.qml:24
+msgctxt "@label"
+msgid "What's new in Ultimaker Cura"
+msgstr "Neuheiten bei Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:42
+msgctxt "@label"
+msgid "There is no printer found over your network."
+msgstr "Kein Drucker in Ihrem Netzwerk gefunden."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:179
+msgctxt "@label"
+msgid "Refresh"
+msgstr "Aktualisieren"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:190
+msgctxt "@label"
+msgid "Add printer by IP"
+msgstr "Drucker nach IP hinzufügen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:223
+msgctxt "@label"
+msgid "Troubleshooting"
+msgstr "Störungen beheben"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:211
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Druckername"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:224
+msgctxt "@text"
+msgid "Please give your printer a name"
+msgstr "Weisen Sie Ihrem Drucker bitte einen Namen zu"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:36
+msgctxt "@label"
+msgid "Ultimaker Cloud"
+msgstr "Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:77
+msgctxt "@text"
+msgid "The next generation 3D printing workflow"
+msgstr "Der 3D-Druckablauf der nächsten Generation"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:94
+msgctxt "@text"
+msgid "- Send print jobs to Ultimaker printers outside your local network"
+msgstr "- Aufträge an Ultimaker-Drucker außerhalb Ihres lokalen Netzwerks senden"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:97
+msgctxt "@text"
+msgid "- Store your Ultimaker Cura settings in the cloud for use anywhere"
+msgstr "- Ihre Ultimaker Cura-Einstellungen für die Verwendung andernorts an die Cloud senden"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:100
+msgctxt "@text"
+msgid "- Get exclusive access to print profiles from leading brands"
+msgstr "- Exklusiven Zugang zu Druckprofilen von führenden Marken erhalten"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:119
+msgctxt "@button"
+msgid "Finish"
+msgstr "Beenden"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:128
+msgctxt "@button"
+msgid "Create an account"
+msgstr "Ein Konto erstellen"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:29
+msgctxt "@label"
+msgid "Welcome to Ultimaker Cura"
+msgstr "Willkommen bei Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:47
+msgctxt "@text"
+msgid ""
+"Please follow these steps to set up\n"
+"Ultimaker Cura. This will only take a few moments."
+msgstr ""
+"Befolgen Sie bitte diese Schritte für das Einrichten von\n"
+"Ultimaker Cura. Dies dauert nur wenige Sekunden."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:58
+msgctxt "@button"
+msgid "Get started"
+msgstr "Erste Schritte"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:27
+msgctxt "@info:tooltip"
+msgid "3D View"
+msgstr "3D-Ansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:40
+msgctxt "@info:tooltip"
+msgid "Front View"
+msgstr "Vorderansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
+msgctxt "@info:tooltip"
+msgid "Top View"
+msgstr "Draufsicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
+msgctxt "@info:tooltip"
+msgid "Left View"
+msgstr "Ansicht von links"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:79
+msgctxt "@info:tooltip"
+msgid "Right View"
+msgstr "Ansicht von rechts"
+
+#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
-msgstr "Ermöglicht das Speichern des resultierenden Slices als X3G-Datei, um Drucker zu unterstützen, die dieses Format lesen (Malyan, Makerbot und andere Sailfish-basierte Drucker)."
+msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
+msgstr "Beschreibt die Durchführung der Geräteeinstellung (z. B. Druckabmessung, Düsengröße usw.)"
-#: X3GWriter/plugin.json
+#: MachineSettingsAction/plugin.json
msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3G-Writer"
+msgid "Machine Settings action"
+msgstr "Beschreibung Geräteeinstellungen"
+
+#: Toolbox/plugin.json
+msgctxt "description"
+msgid "Find, manage and install new Cura packages."
+msgstr "Neue Cura Pakete finden, verwalten und installieren."
+
+#: Toolbox/plugin.json
+msgctxt "name"
+msgid "Toolbox"
+msgstr "Toolbox"
+
+#: XRayView/plugin.json
+msgctxt "description"
+msgid "Provides the X-Ray view."
+msgstr "Stellt die Röntgen-Ansicht bereit."
+
+#: XRayView/plugin.json
+msgctxt "name"
+msgid "X-Ray View"
+msgstr "Röntgen-Ansicht"
+
+#: X3DReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading X3D files."
+msgstr "Bietet Unterstützung für das Lesen von X3D-Dateien."
+
+#: X3DReader/plugin.json
+msgctxt "name"
+msgid "X3D Reader"
+msgstr "X3D-Reader"
+
+#: GCodeWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a file."
+msgstr "Schreibt G-Code in eine Datei."
+
+#: GCodeWriter/plugin.json
+msgctxt "name"
+msgid "G-code Writer"
+msgstr "G-Code-Writer"
+
+#: ModelChecker/plugin.json
+msgctxt "description"
+msgid "Checks models and print configuration for possible printing issues and give suggestions."
+msgstr "Überprüft Modelle und Druckkonfiguration auf mögliche Probleme und erteilt Empfehlungen."
+
+#: ModelChecker/plugin.json
+msgctxt "name"
+msgid "Model Checker"
+msgstr "Modell-Prüfer"
+
+#: FirmwareUpdater/plugin.json
+msgctxt "description"
+msgid "Provides a machine actions for updating firmware."
+msgstr "Ermöglicht Gerätemaßnahmen für die Aktualisierung der Firmware."
+
+#: FirmwareUpdater/plugin.json
+msgctxt "name"
+msgid "Firmware Updater"
+msgstr "Firmware-Aktualisierungsfunktion"
+
+#: AMFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading AMF files."
+msgstr "Ermöglicht das Lesen von AMF-Dateien."
+
+#: AMFReader/plugin.json
+msgctxt "name"
+msgid "AMF Reader"
+msgstr "AMF-Reader"
+
+#: USBPrinting/plugin.json
+msgctxt "description"
+msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
+msgstr "Akzeptiert den G-Code und sendet diesen an einen Drucker. Das Plugin kann auch die Firmware aktualisieren."
+
+#: USBPrinting/plugin.json
+msgctxt "name"
+msgid "USB printing"
+msgstr "USB-Drucken"
+
+#: GCodeGzWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a compressed archive."
+msgstr "G-Code wird in ein komprimiertes Archiv geschrieben."
+
+#: GCodeGzWriter/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Writer"
+msgstr "Writer für komprimierten G-Code"
+
+#: UFPWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing Ultimaker Format Packages."
+msgstr "Bietet Unterstützung für das Schreiben von Ultimaker Format Packages."
+
+#: UFPWriter/plugin.json
+msgctxt "name"
+msgid "UFP Writer"
+msgstr "UFP-Writer"
+
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Bietet eine Vorbereitungsstufe in Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Vorbereitungsstufe"
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "description"
+msgid "Provides removable drive hotplugging and writing support."
+msgstr "Ermöglicht Hotplugging des Wechseldatenträgers und Beschreiben."
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "name"
+msgid "Removable Drive Output Device Plugin"
+msgstr "Ausgabegerät-Plugin für Wechseldatenträger"
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "description"
+msgid "Manages network connections to Ultimaker networked printers."
+msgstr "Verwaltet Netzwerkverbindungen zu Ultimaker-Netzwerkdruckern."
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "name"
+msgid "Ultimaker Network Connection"
+msgstr "Ultimaker-Netzwerkverbindung"
+
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Bietet eine Überwachungsstufe in Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Überwachungsstufe"
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "description"
+msgid "Checks for firmware updates."
+msgstr "Nach Firmware-Updates suchen."
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "name"
+msgid "Firmware Update Checker"
+msgstr "Firmware-Update-Prüfer"
+
+#: SimulationView/plugin.json
+msgctxt "description"
+msgid "Provides the Simulation view."
+msgstr "Ermöglicht die Simulationsansicht."
+
+#: SimulationView/plugin.json
+msgctxt "name"
+msgid "Simulation View"
+msgstr "Simulationsansicht"
+
+#: GCodeGzReader/plugin.json
+msgctxt "description"
+msgid "Reads g-code from a compressed archive."
+msgstr "Liest G-Code-Format aus einem komprimierten Archiv."
+
+#: GCodeGzReader/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Reader"
+msgstr "Reader für komprimierten G-Code"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "description"
+msgid "Extension that allows for user created scripts for post processing"
+msgstr "Erweiterung, die eine Nachbearbeitung von Skripten ermöglicht, die von Benutzern erstellt wurden"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "name"
+msgid "Post Processing"
+msgstr "Nachbearbeitung"
+
+#: SupportEraser/plugin.json
+msgctxt "description"
+msgid "Creates an eraser mesh to block the printing of support in certain places"
+msgstr "Erstellt ein Radierernetz, um den Druck von Stützstrukturen in bestimmten Positionen zu blockieren"
+
+#: SupportEraser/plugin.json
+msgctxt "name"
+msgid "Support Eraser"
+msgstr "Stützstruktur-Radierer"
+
+#: UFPReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading Ultimaker Format Packages."
+msgstr "Bietet Unterstützung für das Lesen von Ultimaker Format Packages."
+
+#: UFPReader/plugin.json
+msgctxt "name"
+msgid "UFP Reader"
+msgstr "UFP-Reader"
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "description"
+msgid "Submits anonymous slice info. Can be disabled through preferences."
+msgstr "Sendet anonymisierte Slice-Informationen. Kann in den Einstellungen deaktiviert werden."
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "name"
+msgid "Slice info"
+msgstr "Slice-Informationen"
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "description"
+msgid "Provides capabilities to read and write XML-based material profiles."
+msgstr "Bietet Möglichkeiten, um XML-basierte Materialprofile zu lesen und zu schreiben."
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "name"
+msgid "Material Profiles"
+msgstr "Materialprofile"
+
+#: LegacyProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from legacy Cura versions."
+msgstr "Bietet Unterstützung für den Import von Profilen der Vorgängerversionen von Cura."
+
+#: LegacyProfileReader/plugin.json
+msgctxt "name"
+msgid "Legacy Cura Profile Reader"
+msgstr "Cura-Vorgängerprofil-Reader"
+
+#: GCodeProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from g-code files."
+msgstr "Ermöglicht das Importieren von Profilen aus G-Code-Dateien."
+
+#: GCodeProfileReader/plugin.json
+msgctxt "name"
+msgid "G-code Profile Reader"
+msgstr "G-Code-Profil-Reader"
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
+msgstr "Aktualisiert Konfigurationen von Cura 3.2 auf Cura 3.3."
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.2 to 3.3"
+msgstr "Upgrade von Version 3.2 auf 3.3"
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
+msgstr "Aktualisiert Konfigurationen von Cura 3.3 auf Cura 3.4."
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.3 to 3.4"
+msgstr "Upgrade von Version 3.3 auf 3.4"
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.3 to Cura 4.4."
+msgstr "Aktualisiert Konfigurationen von Cura 4.3 auf Cura 4.4."
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.3 to 4.4"
+msgstr "Upgrade von Version 4.3 auf 4.4"
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
+msgstr "Aktualisiert Konfigurationen von Cura 2.5 auf Cura 2.6."
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.5 to 2.6"
+msgstr "Upgrade von Version 2.5 auf 2.6"
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
+msgstr "Aktualisiert Konfigurationen von Cura 2.7 auf Cura 3.0."
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.7 to 3.0"
+msgstr "Upgrade von Version 2.7 auf 3.0"
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.5 to Cura 4.0."
+msgstr "Aktualisiert Konfigurationen von Cura 3.5 auf Cura 4.0."
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.5 to 4.0"
+msgstr "Upgrade von Version 3.5 auf 4.0"
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
+msgstr "Aktualisiert Konfigurationen von Cura 3.4 auf Cura 3.5."
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.4 to 3.5"
+msgstr "Upgrade von Version 3.4 auf 3.5"
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.0 to Cura 4.1."
+msgstr "Aktualisiert Konfigurationen von Cura 4.0 auf Cura 4.1."
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.0 to 4.1"
+msgstr "Upgrade von Version 4.0 auf 4.1"
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
+msgstr "Aktualisiert Konfigurationen von Cura 3.0 auf Cura 3.1."
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.0 to 3.1"
+msgstr "Upgrade von Version 3.0 auf 3.1"
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.1 to Cura 4.2."
+msgstr "Aktualisiert Konfigurationen von Cura 4.1 auf Cura 4.2."
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.1 to 4.2"
+msgstr "Upgrade von Version 4.1 auf 4.2"
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
+msgstr "Aktualisiert Konfigurationen von Cura 2.6 auf Cura 2.7."
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.6 to 2.7"
+msgstr "Upgrade von Version 2.6 auf 2.7"
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
+msgstr "Aktualisiert Konfigurationen von Cura 2.1 auf Cura 2.2."
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.1 to 2.2"
+msgstr "Upgrade von Version 2.1 auf 2.2"
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
+msgstr "Aktualisiert Konfigurationen von Cura 2.2 auf Cura 2.4."
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.2 to 2.4"
+msgstr "Upgrade von Version 2.2 auf 2.4"
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.2 to Cura 4.3."
+msgstr "Aktualisiert Konfigurationen von Cura 4.2 auf Cura 4.3."
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.2 to 4.3"
+msgstr "Upgrade von Version 4.2 auf 4.3"
+
+#: ImageReader/plugin.json
+msgctxt "description"
+msgid "Enables ability to generate printable geometry from 2D image files."
+msgstr "Ermöglicht Erstellung von druckbarer Geometrie aus einer 2D-Bilddatei."
+
+#: ImageReader/plugin.json
+msgctxt "name"
+msgid "Image Reader"
+msgstr "Bild-Reader"
+
+#: TrimeshReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading model files."
+msgstr "Unterstützt das Lesen von Modelldateien."
+
+#: TrimeshReader/plugin.json
+msgctxt "name"
+msgid "Trimesh Reader"
+msgstr "Trimesh Reader"
+
+#: CuraEngineBackend/plugin.json
+msgctxt "description"
+msgid "Provides the link to the CuraEngine slicing backend."
+msgstr "Stellt die Verbindung zum Slicing-Backend der CuraEngine her."
+
+#: CuraEngineBackend/plugin.json
+msgctxt "name"
+msgid "CuraEngine Backend"
+msgstr "CuraEngine Backend"
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "description"
+msgid "Provides the Per Model Settings."
+msgstr "Ermöglicht die Einstellungen pro Objekt."
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "name"
+msgid "Per Model Settings Tool"
+msgstr "Werkzeug „Einstellungen pro Objekt“"
+
+#: 3MFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading 3MF files."
+msgstr "Ermöglicht das Lesen von 3MF-Dateien."
+
+#: 3MFReader/plugin.json
+msgctxt "name"
+msgid "3MF Reader"
+msgstr "3MF-Reader"
+
+#: SolidView/plugin.json
+msgctxt "description"
+msgid "Provides a normal solid mesh view."
+msgstr "Bietet eine normale, solide Netzansicht."
+
+#: SolidView/plugin.json
+msgctxt "name"
+msgid "Solid View"
+msgstr "Solide Ansicht"
+
+#: GCodeReader/plugin.json
+msgctxt "description"
+msgid "Allows loading and displaying G-code files."
+msgstr "Ermöglicht das Laden und Anzeigen von G-Code-Dateien."
+
+#: GCodeReader/plugin.json
+msgctxt "name"
+msgid "G-code Reader"
+msgstr "G-Code-Reader"
+
+#: CuraDrive/plugin.json
+msgctxt "description"
+msgid "Backup and restore your configuration."
+msgstr "Sicherung und Wiederherstellen Ihrer Konfiguration."
+
+#: CuraDrive/plugin.json
+msgctxt "name"
+msgid "Cura Backups"
+msgstr "Cura-Backups"
+
+#: CuraProfileWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for exporting Cura profiles."
+msgstr "Ermöglicht das Exportieren von Cura-Profilen."
+
+#: CuraProfileWriter/plugin.json
+msgctxt "name"
+msgid "Cura Profile Writer"
+msgstr "Cura-Profil-Writer"
+
+#: 3MFWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing 3MF files."
+msgstr "Bietet Unterstützung für das Schreiben von 3MF-Dateien."
+
+#: 3MFWriter/plugin.json
+msgctxt "name"
+msgid "3MF Writer"
+msgstr "3MF-Writer"
+
+#: PreviewStage/plugin.json
+msgctxt "description"
+msgid "Provides a preview stage in Cura."
+msgstr "Bietet eine Vorschaustufe in Cura."
+
+#: PreviewStage/plugin.json
+msgctxt "name"
+msgid "Preview Stage"
+msgstr "Vorschaustufe"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "description"
+msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
+msgstr "Ermöglicht Maschinenabläufe für Ultimaker-Maschinen (z. B. Assistent für Bettnivellierung, Auswahl von Upgrades usw.)"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "name"
+msgid "Ultimaker machine actions"
+msgstr "Ultimaker-Maschinenabläufe"
+
+#: CuraProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing Cura profiles."
+msgstr "Ermöglicht das Importieren von Cura-Profilen."
+
+#: CuraProfileReader/plugin.json
+msgctxt "name"
+msgid "Cura Profile Reader"
+msgstr "Cura-Profil-Reader"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Flatten active settings"
+#~ msgstr "Einstellungen Glätten aktiv"
+
+#~ msgctxt "@info:status"
+#~ msgid "Profile has been flattened & activated."
+#~ msgstr "Das Profil wurde geglättet und aktiviert."
+
+#~ msgctxt "X3g Writer Plugin Description"
+#~ msgid "Writes X3g to files"
+#~ msgstr "Schreibt X3g in Dateien"
+
+#~ msgctxt "X3g Writer File Description"
+#~ msgid "X3g File"
+#~ msgstr "X3g-Datei"
+
+#~ msgctxt "X3G Writer File Description"
+#~ msgid "X3G File"
+#~ msgstr "X3G-Datei"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Open Compressed Triangle Mesh"
+#~ msgstr "Öffnen Sie das komprimierte Dreiecksnetz"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Profile Assistant"
+#~ msgstr "Profilassistent"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Profile Assistant"
+#~ msgstr "Profilassistent"
+
+#~ msgctxt "@action:button"
+#~ msgid "Retry"
+#~ msgstr "Erneut versuchen"
+
+#~ msgctxt "@label:table_header"
+#~ msgid "Print Core"
+#~ msgstr "Print Core"
+
+#~ msgctxt "@label"
+#~ msgid "Don't support overlap with other models"
+#~ msgstr "Keine Überlappung mit anderen Modellen unterstützen"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for overlap with other models"
+#~ msgstr "Einstellungen für Überlappung mit anderen Modellen bearbeiten"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for infill of other models"
+#~ msgstr "Einstellungen für Füllung von anderen Modellen bearbeiten"
+
+#~ msgctxt "@action:ComboBox option"
+#~ msgid "Update existing"
+#~ msgstr "Vorhandenes aktualisieren"
+
+#~ msgctxt "@label"
+#~ msgid "Not supported"
+#~ msgstr "Nicht unterstützt"
+
+#~ msgctxt "@action:button"
+#~ msgid "Previous"
+#~ msgstr "Zurück"
+
+#~ msgctxt "@label"
+#~ msgid "Tip"
+#~ msgstr "Tipp"
+
+#~ msgctxt "@label"
+#~ msgid "Print experiment"
+#~ msgstr "Druckexperiment"
+
+#~ msgctxt "@label"
+#~ msgid "Checklist"
+#~ msgstr "Checkliste"
+
+#~ msgctxt "@label"
+#~ msgid "Please select any upgrades made to this Ultimaker 2."
+#~ msgstr "Wählen Sie bitte alle durchgeführten Upgrades für diesen Ultimaker 2."
+
+#~ msgctxt "@label"
+#~ msgid "Olsson Block"
+#~ msgstr "Olsson-Block"
+
+#~ msgctxt "@window:text"
+#~ msgid "Camera rendering: "
+#~ msgstr "Kamera-Rendering: "
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Use multi build plate functionality"
+#~ msgstr "Mehrfach-Druckplattenfunktion verwenden"
+
+#~ msgctxt "@option:check"
+#~ msgid "Use multi build plate functionality (restart required)"
+#~ msgstr "Mehrfach-Druckplattenfunktion verwenden (Neustart erforderlich)"
+
+#~ msgctxt "@label"
+#~ msgid "Default profiles"
+#~ msgstr "Standardprofile"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "search settings"
+#~ msgstr "Einstellungen durchsuchen"
+
+#~ msgctxt "@label"
+#~ msgid "Layer Height"
+#~ msgstr "Schichtdicke"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile."
+#~ msgstr "Dieses Qualitätsprofil ist für Ihr aktuelles Material und Ihre derzeitige Düsenkonfiguration nicht verfügbar. Bitte ändern Sie diese, um das Qualitätsprofil zu aktivieren."
+
+#~ msgctxt "@tooltip"
+#~ msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
+#~ msgstr "Ein benutzerdefiniertes Profil ist derzeit aktiv. Wählen Sie ein voreingestelltes Qualitätsprofil aus der Registerkarte „Benutzerdefiniert“, um den Schieberegler für Qualität zu aktivieren"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Build plate"
+#~ msgstr "&Druckplatte"
+
+#~ msgctxt "@title:settings"
+#~ msgid "&Profile"
+#~ msgstr "&Profil"
+
+#~ msgctxt "@action:label"
+#~ msgid "Build plate"
+#~ msgstr "Druckplatte"
+
+#~ msgctxt "description"
+#~ msgid "Dump the contents of all settings to a HTML file."
+#~ msgstr "Die Inhalte aller Einstellungen in eine HTML-Datei ausgeben."
+
+#~ msgctxt "name"
+#~ msgid "God Mode"
+#~ msgstr "Gott-Modus"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattened quality changes profile."
+#~ msgstr "Erstellt eine geglättete Qualität, verändert das Profil."
+
+#~ msgctxt "name"
+#~ msgid "Profile Flattener"
+#~ msgstr "Profilglättfunktion"
+
+#~ msgctxt "description"
+#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+#~ msgstr "Ermöglichen Sie Materialherstellern die Erstellung neuer Material- und Qualitätsprofile, indem Sie eine Drop-In-Benutzerschnittstelle verwenden."
+
+#~ msgctxt "name"
+#~ msgid "Print Profile Assistant"
+#~ msgstr "Druckprofil-Assistent"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network."
+#~ msgstr "Über Netzwerk verbunden."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. Please approve the access request on the printer."
+#~ msgstr "Über Netzwerk verbunden. Geben Sie die Zugriffsanforderung für den Drucker frei."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. No access to control the printer."
+#~ msgstr "Über Netzwerk verbunden. Kein Zugriff auf die Druckerverwaltung."
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer requested. Please approve the request on the printer"
+#~ msgstr "Zugriff auf Drucker erforderlich. Bestätigen Sie den Zugriff auf den Drucker"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication status"
+#~ msgstr "Authentifizierungsstatus"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication Status"
+#~ msgstr "Authentifizierungsstatus"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Re-send the access request"
+#~ msgstr "Zugriffanforderung erneut senden"
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer accepted"
+#~ msgstr "Zugriff auf den Drucker genehmigt"
+
+#~ msgctxt "@info:status"
+#~ msgid "No access to print with this printer. Unable to send print job."
+#~ msgstr "Kein Zugriff auf das Drucken mit diesem Drucker. Druckauftrag kann nicht gesendet werden."
+
+#~ msgctxt "@action:button"
+#~ msgid "Request Access"
+#~ msgstr "Zugriff anfordern"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Send access request to the printer"
+#~ msgstr "Zugriffsanforderung für den Drucker senden"
+
+#~ msgctxt "@label"
+#~ msgid "Unable to start a new print job."
+#~ msgstr "Es kann kein neuer Druckauftrag gestartet werden."
+
+#~ msgctxt "@label"
+#~ msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
+#~ msgstr "Es liegt ein Problem mit der Konfiguration Ihres Ultimaker vor, das den Druckstart verhindert. Lösen Sie dieses Problem bitte, bevor Sie fortfahren."
+
+#~ msgctxt "@window:title"
+#~ msgid "Mismatched configuration"
+#~ msgstr "Konfiguration nicht übereinstimmend"
+
+#~ msgctxt "@label"
+#~ msgid "Are you sure you wish to print with the selected configuration?"
+#~ msgstr "Möchten Sie wirklich mit der gewählten Konfiguration drucken?"
+
+#~ msgctxt "@label"
+#~ msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Anforderungen zwischen der Druckerkonfiguration oder -kalibrierung und Cura stimmen nicht überein. Für optimale Ergebnisse schneiden Sie stets für die PrintCores und Materialien, die in Ihren Drucker eingelegt wurden."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
+#~ msgstr "Das Senden neuer Aufträge ist (vorübergehend) blockiert; der vorherige Druckauftrag wird noch gesendet."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to printer"
+#~ msgstr "Daten werden zum Drucker gesendet"
+
+#~ msgctxt "@info:title"
+#~ msgid "Sending Data"
+#~ msgstr "Daten werden gesendet"
+
+#~ msgctxt "@info:status"
+#~ msgid "No Printcore loaded in slot {slot_number}"
+#~ msgstr "Kein PrintCore geladen in Steckplatz {slot_number}"
+
+#~ msgctxt "@info:status"
+#~ msgid "No material loaded in slot {slot_number}"
+#~ msgstr "Kein Material geladen in Steckplatz {slot_number}"
+
+#~ msgctxt "@label"
+#~ msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
+#~ msgstr "Abweichender PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) für Extruder gewählt {extruder_id}"
+
+#~ msgctxt "@label"
+#~ msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
+#~ msgstr "Abweichendes Material (Cura: {0}, Drucker: {1}) für Extruder {2} gewählt"
+
+#~ msgctxt "@window:title"
+#~ msgid "Sync with your printer"
+#~ msgstr "Synchronisieren Ihres Druckers"
+
+#~ msgctxt "@label"
+#~ msgid "Would you like to use your current printer configuration in Cura?"
+#~ msgstr "Möchten Sie Ihre aktuelle Druckerkonfiguration in Cura verwenden?"
+
+#~ msgctxt "@label"
+#~ msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Die PrintCores und/oder Materialien auf Ihrem Drucker unterscheiden sich von denen Ihres aktuellen Projekts. Für optimale Ergebnisse schneiden Sie stets für die PrintCores und Materialien, die in Ihren Drucker eingelegt wurden."
+
+#~ msgctxt "@action:button"
+#~ msgid "View in Monitor"
+#~ msgstr "In Monitor überwachen"
+
+#~ msgctxt "@info:status"
+#~ msgid "Printer '{printer_name}' has finished printing '{job_name}'."
+#~ msgstr "Drucker '{printer_name}' hat '{job_name}' vollständig gedrückt."
+
+#~ msgctxt "@info:status"
+#~ msgid "The print job '{job_name}' was finished."
+#~ msgstr "Der Druckauftrag '{job_name}' wurde ausgeführt."
+
+#~ msgctxt "@info:status"
+#~ msgid "Print finished"
+#~ msgstr "Druck vollendet"
+
+#~ msgctxt "@label:material"
+#~ msgid "Empty"
+#~ msgstr "Leer"
+
+#~ msgctxt "@label:material"
+#~ msgid "Unknown"
+#~ msgstr "Unbekannt"
+
+#~ msgctxt "@info:title"
+#~ msgid "Cloud error"
+#~ msgstr "Cloudfehler"
+
+#~ msgctxt "@info:status"
+#~ msgid "Could not export print job."
+#~ msgstr "Druckauftrag konnte nicht exportiert werden."
+
+#~ msgctxt "@info:description"
+#~ msgid "There was an error connecting to the cloud."
+#~ msgstr "Es liegt ein Fehler beim Verbinden mit der Cloud vor."
+
+#~ msgctxt "@info:status"
+#~ msgid "Uploading via Ultimaker Cloud"
+#~ msgstr "Über Ultimaker Cloud hochladen"
+
+#~ msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Verbinden mit Ultimaker Cloud"
+
+#~ msgctxt "@action"
+#~ msgid "Don't ask me again for this printer."
+#~ msgstr "Nicht mehr für diesen Drucker nachfragen."
+
+#~ msgctxt "@info:status"
+#~ msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
+#~ msgstr "Sie können jetzt Druckaufträge mithilfe Ihres Ultimaker-Kontos von einem anderen Ort aus senden und überwachen."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected!"
+#~ msgstr "Verbunden!"
+
+#~ msgctxt "@action"
+#~ msgid "Review your connection"
+#~ msgstr "Ihre Verbindung überprüfen"
+
+#~ msgctxt "@info:status Don't translate the XML tags !"
+#~ msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
+#~ msgstr "Die Maschine, die im Profil {0} ({1}) definiert wurde, entspricht nicht Ihrer derzeitigen Maschine ({2}). Importieren nicht möglich."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}:"
+#~ msgstr "Import des Profils aus Datei {0} fehlgeschlagen:"
+
+#~ msgctxt "@window:title"
+#~ msgid "Existing Connection"
+#~ msgstr "Vorhandene Verbindung"
+
+#~ msgctxt "@message:text"
+#~ msgid "This printer/group is already added to Cura. Please select another printer/group."
+#~ msgstr "Diese/r Drucker/Gruppe wurde bereits zu Cura hinzugefügt. Wählen Sie bitte eine/n andere/n Drucker/Gruppe."
+
+#~ msgctxt "@label"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Geben Sie die IP-Adresse oder den Hostnamen Ihres Druckers auf dem Netzwerk ein."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Connect to a printer"
+#~ msgstr "Mit einem Drucker verbinden"
+
+#~ msgctxt "@title"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Anleitung für Cura-Einstellungen"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Zooming towards the mouse is not supported in the orthogonal perspective."
+#~ msgstr "Das Zoomen in Mausrichtung wird in der Orthogonalansicht nicht unterstützt."
+
+#~ msgid "Orthogonal"
+#~ msgstr "Orthogonal"
+
+#~ msgctxt "description"
+#~ msgid "Manages network connections to Ultimaker 3 printers."
+#~ msgstr "Verwaltet Netzwerkverbindungen zu Ultimaker 3-Druckern."
+
+#~ msgctxt "name"
+#~ msgid "UM3 Network Connection"
+#~ msgstr "UM3-Netzwerkverbindung"
+
+#~ msgctxt "description"
+#~ msgid "Provides extra information and explanations about settings in Cura, with images and animations."
+#~ msgstr "Bietet zusätzliche Informationen und Erklärungen zu den Einstellungen in Cura mit Abbildungen und Animationen."
+
+#~ msgctxt "name"
+#~ msgid "Settings Guide"
+#~ msgstr "Anleitung für Einstellungen"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Anleitung für Cura-Einstellungen"
+
+#~ msgctxt "@info:generic"
+#~ msgid "Settings have been changed to match the current availability of extruders: [%s]"
+#~ msgstr "Die Einstellungen wurden passend für die aktuelle Verfügbarkeit der Extruder geändert: [%s]"
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "User description"
+#~ msgstr "Benutzerbeschreibung"
+
+#~ msgctxt "@info"
+#~ msgid "These options are not available because you are monitoring a cloud printer."
+#~ msgstr "Diese Optionen sind nicht verfügbar, weil Sie einen Cloud-Drucker überwachen."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Go to Cura Connect"
+#~ msgstr "Gehe zu Cura Connect"
+
+#~ msgctxt "@info"
+#~ msgid "All jobs are printed."
+#~ msgstr "Alle Aufträge wurden gedruckt."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "View print history"
+#~ msgstr "Druckauftragshistorie anzeigen"
+
+#~ msgctxt "@label"
+#~ msgid ""
+#~ "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
+#~ "\n"
+#~ "Select your printer from the list below:"
+#~ msgstr ""
+#~ "Um über das Netzwerk direkt auf Ihrem Drucker zu drucken, stellen Sie bitte sicher, dass der Drucker mit dem Netzwerkkabel verbunden ist oder verbinden Sie Ihren Drucker mit Ihrem WLAN-Netzwerk. Wenn Sie Cura nicht mit Ihrem Drucker verbinden, können Sie dennoch ein USB-Laufwerk für die Übertragung von G-Code-Dateien auf Ihren Drucker verwenden.\n"
+#~ "\n"
+#~ "Wählen Sie Ihren Drucker aus der folgenden Liste:"
+
+#~ msgctxt "@info"
+#~ msgid ""
+#~ "Please make sure your printer has a connection:\n"
+#~ "- Check if the printer is turned on.\n"
+#~ "- Check if the printer is connected to the network."
+#~ msgstr ""
+#~ "Stellen Sie bitte sicher, dass Ihr Drucker verbunden ist:\n"
+#~ "- Prüfen Sie, ob Ihr Drucker eingeschaltet ist.\n"
+#~ "- Prüfen Sie, ob der Drucker mit dem Netzwerk verbunden ist."
+
+#~ msgctxt "@option:check"
+#~ msgid "See only current build plate"
+#~ msgstr "Nur aktuelle Druckplatte anzeigen"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange to all build plates"
+#~ msgstr "An allen Druckplatten ausrichten"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange current build plate"
+#~ msgstr "An aktueller Druckplatte ausrichten"
+
+#~ msgctxt "description"
+#~ msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
+#~ msgstr "Ermöglicht das Speichern des resultierenden Slices als X3G-Datei, um Drucker zu unterstützen, die dieses Format lesen (Malyan, Makerbot und andere Sailfish-basierte Drucker)."
+
+#~ msgctxt "name"
+#~ msgid "X3GWriter"
+#~ msgstr "X3G-Writer"
+
+#~ msgctxt "description"
+#~ msgid "Reads SVG files as toolpaths, for debugging printer movements."
+#~ msgstr "Liest SVG-Dateien als Werkzeugwege für die Fehlersuche bei Druckerbewegungen."
+
+#~ msgctxt "name"
+#~ msgid "SVG Toolpath Reader"
+#~ msgstr "SVG-Werkzeugweg-Reader"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Changelog"
+#~ msgstr "Änderungsprotokoll"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Show Changelog"
+#~ msgstr "Änderungsprotokoll anzeigen"
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to remote cluster"
+#~ msgstr "Daten werden zu Remote-Cluster gesendet"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Verbinden mit Ultimaker Cloud"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymized usage statistics."
+#~ msgstr "Cura erfasst anonymisierte Nutzungsstatistiken."
+
+#~ msgctxt "@info:title"
+#~ msgid "Collecting Data"
+#~ msgstr "Daten werden erfasst"
+
+#~ msgctxt "@action:button"
+#~ msgid "More info"
+#~ msgstr "Mehr Infos"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "See more information on what data Cura sends."
+#~ msgstr "Siehe mehr Informationen dazu, was Cura sendet."
+
+#~ msgctxt "@action:button"
+#~ msgid "Allow"
+#~ msgstr "Zulassen"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
+#~ msgstr "Damit lassen Sie zu, dass Cura anonymisierte Nutzungsstatistiken sendet, um zukünftige Verbesserungen für Cura zu definieren. Einige Ihrer Präferenzen und Einstellungen, die Cura-Version und ein Hash der Modelle, die Sie slicen, werden gesendet."
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Evaluation"
+#~ msgstr "Bewertung"
+
+#~ msgctxt "@info:title"
+#~ msgid "Network enabled printers"
+#~ msgstr "Netzwerkfähige Drucker"
+
+#~ msgctxt "@info:title"
+#~ msgid "Local printers"
+#~ msgstr "Lokale Drucker"
+
+#~ msgctxt "@info:backup_failed"
+#~ msgid "Tried to restore a Cura backup that does not match your current version."
+#~ msgstr "Versucht, ein Cura-Backup zu erstellen, das nicht Ihrer aktuellen Version entspricht."
+
+#~ msgctxt "@title"
+#~ msgid "Machine Settings"
+#~ msgstr "Geräteeinstellungen"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Settings"
+#~ msgstr "Druckereinstellungen"
+
+#~ msgctxt "@option:check"
+#~ msgid "Origin at center"
+#~ msgstr "Ausgang in Mitte"
+
+#~ msgctxt "@option:check"
+#~ msgid "Heated bed"
+#~ msgstr "Heizbares Bett"
+
+#~ msgctxt "@label"
+#~ msgid "Printhead Settings"
+#~ msgstr "Druckkopfeinstellungen"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Abstand von der linken Seite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Abstand von der Vorderseite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Abstand von der rechten Seite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Abstand von der Rückseite des Druckkopfes zur Düsenmitte. Wird verwendet, um Kollisionen zwischen vorherigen Drucken und dem Druckkopf während des Druckmodus „Nacheinander“ zu vermeiden."
+
+#~ msgctxt "@label"
+#~ msgid "Gantry height"
+#~ msgstr "Brückenhöhe"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
+#~ msgstr "Der Höhenunterschied zwischen der Düsenspitze und dem Brückensystem (X- und Y-Achsen). Wird verwendet, um Kollisionen zwischen vorherigen Drucken und der Brücke zu verhindern, wenn im Modus „Nacheinander“ gedruckt wird."
+
+#~ msgctxt "@label"
+#~ msgid "Start G-code"
+#~ msgstr "Start G-code"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very start."
+#~ msgstr "G-Code-Befehle, die zum Start ausgeführt werden sollen."
+
+#~ msgctxt "@label"
+#~ msgid "End G-code"
+#~ msgstr "Ende G-code"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very end."
+#~ msgstr "G-Code-Befehle, die am Ende ausgeführt werden sollen."
+
+#~ msgctxt "@label"
+#~ msgid "Nozzle Settings"
+#~ msgstr "Düseneinstellungen"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
+#~ msgstr "Der Nenndurchmesser des durch den Drucker unterstützten Filaments. Der exakte Durchmesser wird durch das Material und/oder das Profil überschrieben."
+
+#~ msgctxt "@label"
+#~ msgid "Extruder Start G-code"
+#~ msgstr "G-Code Extruder-Start"
+
+#~ msgctxt "@label"
+#~ msgid "Extruder End G-code"
+#~ msgstr "G-Code Extruder-Ende"
+
+#~ msgctxt "@label"
+#~ msgid "Changelog"
+#~ msgstr "Änderungsprotokoll"
+
+#~ msgctxt "@title:window"
+#~ msgid "User Agreement"
+#~ msgstr "Benutzervereinbarung"
+
+#~ msgctxt "@alabel"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Geben Sie die IP-Adresse oder den Hostnamen Ihres Druckers auf dem Netzwerk ein."
+
+#~ msgctxt "@info"
+#~ msgid "Please select a network connected printer to monitor."
+#~ msgstr "Bitte einen mit dem Netzwerk verbunden Drucker für die Überwachung wählen."
+
+#~ msgctxt "@info"
+#~ msgid "Please connect your Ultimaker printer to your local network."
+#~ msgstr "Verbinden Sie Ihren Ultimaker-Drucker bitte mit Ihrem lokalen Netzwerk."
+
+#~ msgctxt "@text:window"
+#~ msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
+#~ msgstr "Cura sendet anonyme Daten an Ultimaker, um die Druckqualität und Benutzererfahrung zu steigern. Nachfolgend ist ein Beispiel aller Daten, die gesendet werden."
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send this data"
+#~ msgstr "Ich möchte diese Daten nicht senden"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending this data to Ultimaker and help us improve Cura"
+#~ msgstr "Ich erlaube das Senden der Daten an Ultimaker, um Cura zu verbessern"
+
+#~ msgctxt "@label"
+#~ msgid "No print selected"
+#~ msgstr "Kein Druck ausgewählt"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
+#~ msgstr "Standardmäßig repräsentieren weiße Pixel hohe Punkte im Netz und schwarze Pixel repräsentieren niedrige Punkte im Netz. Ändern Sie diese Option um das Verhalten so umzukehren, dass schwarze Pixel hohe Punkte im Netz darstellen und weiße Pixel niedrige Punkte im Netz."
+
+#~ msgctxt "@title"
+#~ msgid "Select Printer Upgrades"
+#~ msgstr "Drucker-Upgrades wählen"
+
+#~ msgctxt "@label"
+#~ msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
+#~ msgstr "Wählen Sie, welcher Extruder für die Unterstützung verwendet wird. Dient zum Konstruieren von Stützstrukturen unter dem Modell, damit dieses nicht absinkt oder frei schwebend gedruckt wird."
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
+#~ msgstr "Dieses Qualitätsprofil ist für Ihr aktuelles Material und Ihre derzeitige Düsenkonfiguration nicht verfügbar. Bitte ändern Sie diese, um das Qualitätsprofil zu aktivieren."
+
+#~ msgctxt "@label shown when we load a Gcode file"
+#~ msgid "Print setup disabled. G code file can not be modified."
+#~ msgstr "Druckeinrichtung ist deaktiviert. G-Code kann nicht geändert werden."
+
+#~ msgctxt "@label"
+#~ msgid "See the material compatibility chart"
+#~ msgstr "Siehe Materialkompatibilitätstabelle"
+
+#~ msgctxt "@label"
+#~ msgid "View types"
+#~ msgstr "Typen anzeigen"
+
+#~ msgctxt "@label"
+#~ msgid "Hi "
+#~ msgstr "Hallo "
+
+#~ msgctxt "@text"
+#~ msgid ""
+#~ "- Send print jobs to Ultimaker printers outside your local network\n"
+#~ "- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
+#~ "- Get exclusive access to material profiles from leading brands"
+#~ msgstr ""
+#~ "- Aufträge an Ultimaker-Drucker außerhalb Ihres lokalen Netzwerks senden\n"
+#~ "- Ihre Ultimaker Cura-Einstellungen für die Verwendung andernorts an die Cloud senden\n"
+#~ "- Exklusiven Zugang zu Materialprofilen von führenden Marken erhalten"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Unable to Slice"
+#~ msgstr "Slicing nicht möglich"
+
+#~ msgctxt "@label"
+#~ msgid "Time specification"
+#~ msgstr "Zeitangabe"
+
+#~ msgctxt "@label"
+#~ msgid "Material specification"
+#~ msgstr "Materialangabe"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Add a printer to Cura"
+#~ msgstr "Fügen Sie einen Drucker zu Cura hinzu"
+
+#~ msgctxt "@title:tab"
+#~ msgid ""
+#~ "Select the printer you want to use from the list below.\n"
+#~ "\n"
+#~ "If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
+#~ msgstr ""
+#~ "Wählen Sie den zu verwendenden Drucker aus der nachfolgenden Liste.\n"
+#~ "\n"
+#~ "Wenn Ihr Drucker nicht in der Liste aufgeführt ist, verwenden Sie „Benutzerdefinierter FFF-Drucker“ aus der Kategorie „Benutzerdefiniert“ und passen Sie die Einstellungen im folgenden Dialog passend für Ihren Drucker an."
+
+#~ msgctxt "@label"
+#~ msgid "Manufacturer"
+#~ msgstr "Hersteller"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name"
+#~ msgstr "Druckername"
+
+#~ msgctxt "@action:button"
+#~ msgid "Add Printer"
+#~ msgstr "Drucker hinzufügen"
#~ msgid "Modify G-Code"
#~ msgstr "G-Code ändern"
@@ -5328,62 +6474,6 @@ msgstr "X3G-Writer"
#~ msgid "Click to check the material compatibility on Ultimaker.com."
#~ msgstr "Klicken Sie, um die Materialkompatibilität auf Ultimaker.com zu prüfen."
-#~ msgctxt "description"
-#~ msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
-#~ msgstr "Beschreibt die Durchführung der Geräteeinstellung (z. B. Druckabmessung, Düsengröße usw.)"
-
-#~ msgctxt "name"
-#~ msgid "Machine Settings action"
-#~ msgstr "Beschreibung Geräteeinstellungen"
-
-#~ msgctxt "description"
-#~ msgid "Find, manage and install new Cura packages."
-#~ msgstr "Neue Cura Pakete finden, verwalten und installieren."
-
-#~ msgctxt "name"
-#~ msgid "Toolbox"
-#~ msgstr "Toolbox"
-
-#~ msgctxt "description"
-#~ msgid "Provides the X-Ray view."
-#~ msgstr "Stellt die Röntgen-Ansicht bereit."
-
-#~ msgctxt "name"
-#~ msgid "X-Ray View"
-#~ msgstr "Röntgen-Ansicht"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading X3D files."
-#~ msgstr "Bietet Unterstützung für das Lesen von X3D-Dateien."
-
-#~ msgctxt "name"
-#~ msgid "X3D Reader"
-#~ msgstr "X3D-Reader"
-
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a file."
-#~ msgstr "Schreibt G-Code in eine Datei."
-
-#~ msgctxt "name"
-#~ msgid "G-code Writer"
-#~ msgstr "G-Code-Writer"
-
-#~ msgctxt "description"
-#~ msgid "Checks models and print configuration for possible printing issues and give suggestions."
-#~ msgstr "Überprüft Modelle und Druckkonfiguration auf mögliche Probleme und erteilt Empfehlungen."
-
-#~ msgctxt "name"
-#~ msgid "Model Checker"
-#~ msgstr "Modell-Prüfer"
-
-#~ msgctxt "description"
-#~ msgid "Dump the contents of all settings to a HTML file."
-#~ msgstr "Die Inhalte aller Einstellungen in eine HTML-Datei ausgeben."
-
-#~ msgctxt "name"
-#~ msgid "God Mode"
-#~ msgstr "Gott-Modus"
-
#~ msgctxt "description"
#~ msgid "Shows changes since latest checked version."
#~ msgstr "Zeigt die Änderungen seit der letzten geprüften Version an."
@@ -5392,14 +6482,6 @@ msgstr "X3G-Writer"
#~ msgid "Changelog"
#~ msgstr "Änderungsprotokoll"
-#~ msgctxt "description"
-#~ msgid "Provides a machine actions for updating firmware."
-#~ msgstr "Ermöglicht Gerätemaßnahmen für die Aktualisierung der Firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Updater"
-#~ msgstr "Firmware-Aktualisierungsfunktion"
-
#~ msgctxt "description"
#~ msgid "Create a flattend quality changes profile."
#~ msgstr "Erstellt eine geglättete Qualität, verändert das Profil."
@@ -5408,14 +6490,6 @@ msgstr "X3G-Writer"
#~ msgid "Profile flatener"
#~ msgstr "Profilglättfunktion"
-#~ msgctxt "description"
-#~ msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
-#~ msgstr "Akzeptiert den G-Code und sendet diesen an einen Drucker. Das Plugin kann auch die Firmware aktualisieren."
-
-#~ msgctxt "name"
-#~ msgid "USB printing"
-#~ msgstr "USB-Drucken"
-
#~ msgctxt "description"
#~ msgid "Ask the user once if he/she agrees with our license."
#~ msgstr "Den Benutzer einmalig fragen, ob er unsere Lizenz akzeptiert."
@@ -5424,278 +6498,6 @@ msgstr "X3G-Writer"
#~ msgid "UserAgreement"
#~ msgstr "UserAgreement"
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a compressed archive."
-#~ msgstr "G-Code wird in ein komprimiertes Archiv geschrieben."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Writer"
-#~ msgstr "Writer für komprimierten G-Code"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing Ultimaker Format Packages."
-#~ msgstr "Bietet Unterstützung für das Schreiben von Ultimaker Format Packages."
-
-#~ msgctxt "name"
-#~ msgid "UFP Writer"
-#~ msgstr "UFP-Writer"
-
-#~ msgctxt "description"
-#~ msgid "Provides a prepare stage in Cura."
-#~ msgstr "Bietet eine Vorbereitungsstufe in Cura."
-
-#~ msgctxt "name"
-#~ msgid "Prepare Stage"
-#~ msgstr "Vorbereitungsstufe"
-
-#~ msgctxt "description"
-#~ msgid "Provides removable drive hotplugging and writing support."
-#~ msgstr "Ermöglicht Hotplugging des Wechseldatenträgers und Beschreiben."
-
-#~ msgctxt "name"
-#~ msgid "Removable Drive Output Device Plugin"
-#~ msgstr "Ausgabegerät-Plugin für Wechseldatenträger"
-
-#~ msgctxt "description"
-#~ msgid "Manages network connections to Ultimaker 3 printers."
-#~ msgstr "Verwaltet Netzwerkverbindungen zu Ultimaker 3-Druckern."
-
-#~ msgctxt "name"
-#~ msgid "UM3 Network Connection"
-#~ msgstr "UM3-Netzwerkverbindung"
-
-#~ msgctxt "description"
-#~ msgid "Provides a monitor stage in Cura."
-#~ msgstr "Bietet eine Überwachungsstufe in Cura."
-
-#~ msgctxt "name"
-#~ msgid "Monitor Stage"
-#~ msgstr "Überwachungsstufe"
-
-#~ msgctxt "description"
-#~ msgid "Checks for firmware updates."
-#~ msgstr "Nach Firmware-Updates suchen."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Update Checker"
-#~ msgstr "Firmware-Update-Prüfer"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Simulation view."
-#~ msgstr "Ermöglicht die Simulationsansicht."
-
-#~ msgctxt "name"
-#~ msgid "Simulation View"
-#~ msgstr "Simulationsansicht"
-
-#~ msgctxt "description"
-#~ msgid "Reads g-code from a compressed archive."
-#~ msgstr "Liest G-Code-Format aus einem komprimierten Archiv."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Reader"
-#~ msgstr "Reader für komprimierten G-Code"
-
-#~ msgctxt "description"
-#~ msgid "Extension that allows for user created scripts for post processing"
-#~ msgstr "Erweiterung, die eine Nachbearbeitung von Skripten ermöglicht, die von Benutzern erstellt wurden"
-
-#~ msgctxt "name"
-#~ msgid "Post Processing"
-#~ msgstr "Nachbearbeitung"
-
-#~ msgctxt "description"
-#~ msgid "Creates an eraser mesh to block the printing of support in certain places"
-#~ msgstr "Erstellt ein Radierernetz, um den Druck von Stützstrukturen in bestimmten Positionen zu blockieren"
-
-#~ msgctxt "name"
-#~ msgid "Support Eraser"
-#~ msgstr "Stützstruktur-Radierer"
-
-#~ msgctxt "description"
-#~ msgid "Submits anonymous slice info. Can be disabled through preferences."
-#~ msgstr "Sendet anonymisierte Slice-Informationen. Kann in den Einstellungen deaktiviert werden."
-
-#~ msgctxt "name"
-#~ msgid "Slice info"
-#~ msgstr "Slice-Informationen"
-
-#~ msgctxt "description"
-#~ msgid "Provides capabilities to read and write XML-based material profiles."
-#~ msgstr "Bietet Möglichkeiten, um XML-basierte Materialprofile zu lesen und zu schreiben."
-
-#~ msgctxt "name"
-#~ msgid "Material Profiles"
-#~ msgstr "Materialprofile"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from legacy Cura versions."
-#~ msgstr "Bietet Unterstützung für den Import von Profilen der Vorgängerversionen von Cura."
-
-#~ msgctxt "name"
-#~ msgid "Legacy Cura Profile Reader"
-#~ msgstr "Cura-Vorgängerprofil-Reader"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from g-code files."
-#~ msgstr "Ermöglicht das Importieren von Profilen aus G-Code-Dateien."
-
-#~ msgctxt "name"
-#~ msgid "G-code Profile Reader"
-#~ msgstr "G-Code-Profil-Reader"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 3.2 auf Cura 3.3."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.2 to 3.3"
-#~ msgstr "Upgrade von Version 3.2 auf 3.3"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 3.3 auf Cura 3.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.3 to 3.4"
-#~ msgstr "Upgrade von Version 3.3 auf 3.4"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 2.5 auf Cura 2.6."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.5 to 2.6"
-#~ msgstr "Upgrade von Version 2.5 auf 2.6"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 2.7 auf Cura 3.0."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.7 to 3.0"
-#~ msgstr "Upgrade von Version 2.7 auf 3.0"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 3.4 auf Cura 3.5."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.4 to 3.5"
-#~ msgstr "Upgrade von Version 3.4 auf 3.5"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 3.0 auf Cura 3.1."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.0 to 3.1"
-#~ msgstr "Upgrade von Version 3.0 auf 3.1"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 2.6 auf Cura 2.7."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.6 to 2.7"
-#~ msgstr "Upgrade von Version 2.6 auf 2.7"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 2.1 auf Cura 2.2."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.1 to 2.2"
-#~ msgstr "Upgrade von Version 2.1 auf 2.2"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
-#~ msgstr "Aktualisiert Konfigurationen von Cura 2.2 auf Cura 2.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.2 to 2.4"
-#~ msgstr "Upgrade von Version 2.2 auf 2.4"
-
-#~ msgctxt "description"
-#~ msgid "Enables ability to generate printable geometry from 2D image files."
-#~ msgstr "Ermöglicht Erstellung von druckbarer Geometrie aus einer 2D-Bilddatei."
-
-#~ msgctxt "name"
-#~ msgid "Image Reader"
-#~ msgstr "Bild-Reader"
-
-#~ msgctxt "description"
-#~ msgid "Provides the link to the CuraEngine slicing backend."
-#~ msgstr "Stellt die Verbindung zum Slicing-Backend der CuraEngine her."
-
-#~ msgctxt "name"
-#~ msgid "CuraEngine Backend"
-#~ msgstr "CuraEngine Backend"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Per Model Settings."
-#~ msgstr "Ermöglicht die Einstellungen pro Objekt."
-
-#~ msgctxt "name"
-#~ msgid "Per Model Settings Tool"
-#~ msgstr "Werkzeug „Einstellungen pro Objekt“"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading 3MF files."
-#~ msgstr "Ermöglicht das Lesen von 3MF-Dateien."
-
-#~ msgctxt "name"
-#~ msgid "3MF Reader"
-#~ msgstr "3MF-Reader"
-
-#~ msgctxt "description"
-#~ msgid "Provides a normal solid mesh view."
-#~ msgstr "Bietet eine normale, solide Netzansicht."
-
-#~ msgctxt "name"
-#~ msgid "Solid View"
-#~ msgstr "Solide Ansicht"
-
-#~ msgctxt "description"
-#~ msgid "Allows loading and displaying G-code files."
-#~ msgstr "Ermöglicht das Laden und Anzeigen von G-Code-Dateien."
-
-#~ msgctxt "name"
-#~ msgid "G-code Reader"
-#~ msgstr "G-Code-Reader"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for exporting Cura profiles."
-#~ msgstr "Ermöglicht das Exportieren von Cura-Profilen."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Writer"
-#~ msgstr "Cura-Profil-Writer"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing 3MF files."
-#~ msgstr "Bietet Unterstützung für das Schreiben von 3MF-Dateien."
-
-#~ msgctxt "name"
-#~ msgid "3MF Writer"
-#~ msgstr "3MF-Writer"
-
-#~ msgctxt "description"
-#~ msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
-#~ msgstr "Ermöglicht Maschinenabläufe für Ultimaker-Maschinen (z. B. Assistent für Bettnivellierung, Auswahl von Upgrades usw.)"
-
-#~ msgctxt "name"
-#~ msgid "Ultimaker machine actions"
-#~ msgstr "Ultimaker-Maschinenabläufe"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing Cura profiles."
-#~ msgstr "Ermöglicht das Importieren von Cura-Profilen."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Reader"
-#~ msgstr "Cura-Profil-Reader"
-
#~ msgctxt "@warning:status"
#~ msgid "Please generate G-code before saving."
#~ msgstr "Generieren Sie vor dem Speichern bitte einen G-Code."
@@ -5736,14 +6538,6 @@ msgstr "X3G-Writer"
#~ msgid "Upgrade Firmware"
#~ msgstr "Firmware aktualisieren"
-#~ msgctxt "description"
-#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
-#~ msgstr "Ermöglichen Sie Materialherstellern die Erstellung neuer Material- und Qualitätsprofile, indem Sie eine Drop-In-Benutzerschnittstelle verwenden."
-
-#~ msgctxt "name"
-#~ msgid "Print Profile Assistant"
-#~ msgstr "Druckprofil-Assistent"
-
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Mit Doodle3D WLAN-Box drucken"
diff --git a/resources/i18n/de_DE/fdmextruder.def.json.po b/resources/i18n/de_DE/fdmextruder.def.json.po
index 4bb0cc0705..cc39f59f72 100644
--- a/resources/i18n/de_DE/fdmextruder.def.json.po
+++ b/resources/i18n/de_DE/fdmextruder.def.json.po
@@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -84,7 +84,7 @@ msgstr "G-Code Extruder-Start"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
msgid "Start g-code to execute when switching to this extruder."
-msgstr ""
+msgstr "Auszuführenden G-Code beim Umschalten auf diesen Extruder starten."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -124,7 +124,7 @@ msgstr "G-Code Extruder-Ende"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
msgid "End g-code to execute when switching away from this extruder."
-msgstr ""
+msgstr "Auszuführenden G-Code beim Umschalten von diesem Extruder beenden."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
diff --git a/resources/i18n/de_DE/fdmprinter.def.json.po b/resources/i18n/de_DE/fdmprinter.def.json.po
index 360aaf0672..aee5ae4ace 100644
--- a/resources/i18n/de_DE/fdmprinter.def.json.po
+++ b/resources/i18n/de_DE/fdmprinter.def.json.po
@@ -5,12 +5,12 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 14:57+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: German\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: German , German \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -215,6 +215,16 @@ msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
msgstr "Option für vorhandene beheizte Druckplatte."
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume label"
+msgid "Has Build Volume Temperature Stabilization"
+msgstr "Verfügt über Temperaturstabilisierung für den Druckraum"
+
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume description"
+msgid "Whether the machine is able to stabilize the build volume temperature."
+msgstr "Zeigt an, ob das Gerät die Temperatur im Druckraum stabilisieren kann."
+
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
@@ -237,7 +247,7 @@ msgstr "Anzahl der Extruder-Elemente. Ein Extruder-Element ist die Kombination a
#: fdmprinter.def.json
msgctxt "extruders_enabled_count label"
-msgid "Number of Extruders that are enabled"
+msgid "Number of Extruders That Are Enabled"
msgstr "Anzahl der aktivierten Extruder"
#: fdmprinter.def.json
@@ -247,7 +257,7 @@ msgstr "Anzahl der aktivierten Extruder-Elemente; wird automatisch in der Softwa
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
-msgid "Outer nozzle diameter"
+msgid "Outer Nozzle Diameter"
msgstr "Düsendurchmesser außen"
#: fdmprinter.def.json
@@ -257,7 +267,7 @@ msgstr "Der Außendurchmesser der Düsenspitze."
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
+msgid "Nozzle Length"
msgstr "Düsenlänge"
#: fdmprinter.def.json
@@ -267,7 +277,7 @@ msgstr "Der Höhenunterschied zwischen der Düsenspitze und dem untersten Bereic
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
+msgid "Nozzle Angle"
msgstr "Düsenwinkel"
#: fdmprinter.def.json
@@ -277,7 +287,7 @@ msgstr "Der Winkel zwischen der horizontalen Planfläche und dem konischen Teil
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length label"
-msgid "Heat zone length"
+msgid "Heat Zone Length"
msgstr "Heizzonenlänge"
#: fdmprinter.def.json
@@ -307,7 +317,7 @@ msgstr "Für die Temperatursteuerung von Cura. Schalten Sie diese Funktion aus,
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed label"
-msgid "Heat up speed"
+msgid "Heat Up Speed"
msgstr "Aufheizgeschwindigkeit"
#: fdmprinter.def.json
@@ -317,7 +327,7 @@ msgstr "Die Geschwindigkeit (°C/Sek.), mit der die Düse durchschnittlich bei n
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed label"
-msgid "Cool down speed"
+msgid "Cool Down Speed"
msgstr "Abkühlgeschwindigkeit"
#: fdmprinter.def.json
@@ -337,7 +347,7 @@ msgstr "Die Mindestzeit, die ein Extruder inaktiv sein muss, bevor die Düse abk
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
+msgid "G-code Flavor"
msgstr "G-Code-Variante"
#: fdmprinter.def.json
@@ -402,7 +412,7 @@ msgstr "Definiert, ob Firmware-Einzugsbefehle (G10/G11) anstelle der E-Eigenscha
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
+msgid "Disallowed Areas"
msgstr "Unzulässige Bereiche"
#: fdmprinter.def.json
@@ -422,7 +432,7 @@ msgstr "Eine Liste mit Polygonen mit Bereichen, in welche die Düse nicht eintre
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
+msgid "Machine Head Polygon"
msgstr "Gerätekopf Polygon"
#: fdmprinter.def.json
@@ -432,7 +442,7 @@ msgstr "Eine 2D-Shilhouette des Druckkopfes (ohne Lüfterkappen)."
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
-msgid "Machine head & Fan polygon"
+msgid "Machine Head & Fan Polygon"
msgstr "Gerätekopf und Lüfter Polygon"
#: fdmprinter.def.json
@@ -442,7 +452,7 @@ msgstr "Eine 2D-Shilhouette des Druckkopfes (mit Lüfterkappen)."
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Brückenhöhe"
#: fdmprinter.def.json
@@ -472,7 +482,7 @@ msgstr "Der Innendurchmesser der Düse. Verwenden Sie diese Einstellung, wenn Si
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label"
-msgid "Offset With Extruder"
+msgid "Offset with Extruder"
msgstr "Versatz mit Extruder"
#: fdmprinter.def.json
@@ -1020,6 +1030,17 @@ msgctxt "bottom_layers description"
msgid "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number."
msgstr "Die Anzahl der unteren Schichten. Wenn diese anhand der unteren Dicke berechnet wird, wird der Wert auf eine ganze Zahl auf- oder abgerundet."
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers label"
+msgid "Initial Bottom Layers"
+msgstr "Erste untere Schichten"
+
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers description"
+msgid "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number."
+msgstr "Die Anzahl der ersten Schichten, die auf die Druckplatte aufgetragen werden. Wenn diese anhand der unteren Dicke berechnet werden, wird der Wert auf eine"
+" ganze Zahl auf- oder abgerundet."
+
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
@@ -1270,6 +1291,56 @@ msgctxt "z_seam_type option sharpest_corner"
msgid "Sharpest Corner"
msgstr "Schärfste Kante"
+#: fdmprinter.def.json
+msgctxt "z_seam_position label"
+msgid "Z Seam Position"
+msgstr "Position der Z-Naht"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position description"
+msgid "The position near where to start printing each part in a layer."
+msgstr "Die Position in der Nähe der Stelle, an der die einzelnen Teile einer Ebene gedruckt werden sollen."
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backleft"
+msgid "Back Left"
+msgstr "Hinten links"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option back"
+msgid "Back"
+msgstr "Zurück"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backright"
+msgid "Back Right"
+msgstr "Hinten rechts"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option right"
+msgid "Right"
+msgstr "Rechts"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontright"
+msgid "Front Right"
+msgstr "Vorne rechts"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option front"
+msgid "Front"
+msgstr "Vorne"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontleft"
+msgid "Front Left"
+msgstr "Vorne links"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option left"
+msgid "Left"
+msgstr "Links"
+
#: fdmprinter.def.json
msgctxt "z_seam_x label"
msgid "Z Seam X"
@@ -1297,8 +1368,8 @@ msgstr "Präferenz Nahtkante"
#: fdmprinter.def.json
msgctxt "z_seam_corner description"
-msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
-msgstr "Definieren Sie, ob Kanten am Modell-Umriss die Nahtposition beeinflussen. Keine bedeutet, dass Kanten keinen Einfluss auf die Nahtposition haben. Naht verbergen lässt die Naht mit höherer Wahrscheinlichkeit an einer innenliegenden Kante auftreten. Naht offenlegen lässt die Naht mit höherer Wahrscheinlichkeit an einer Außenkante auftreten. Naht verbergen oder offenlegen lässt die Naht mit höherer Wahrscheinlichkeit an einer innenliegenden oder außenliegenden Kante auftreten."
+msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner. Smart Hiding allows both inside and outside corners, but chooses inside corners more frequently, if appropriate."
+msgstr "Definieren Sie, ob Kanten am Modell-Umriss die Nahtposition beeinflussen. Keine bedeutet, dass Kanten keinen Einfluss auf die Nahtposition haben. Naht verbergen lässt die Naht mit höherer Wahrscheinlichkeit an einer innenliegenden Kante auftreten. Naht offenlegen lässt die Naht mit höherer Wahrscheinlichkeit an einer Außenkante auftreten. Naht verbergen oder offenlegen lässt die Naht mit höherer Wahrscheinlichkeit an einer innenliegenden oder außenliegenden Kante auftreten. Intelligent verbergen lässt die Naht an innen- oder außenliegenden Kanten auftreten, verwendet aber – falls zweckmäßig – häufiger innenliegende Kanten."
#: fdmprinter.def.json
msgctxt "z_seam_corner option z_seam_corner_none"
@@ -1320,6 +1391,11 @@ msgctxt "z_seam_corner option z_seam_corner_any"
msgid "Hide or Expose Seam"
msgstr "Naht verbergen oder offenlegen"
+#: fdmprinter.def.json
+msgctxt "z_seam_corner option z_seam_corner_weighted"
+msgid "Smart Hiding"
+msgstr "Intelligent verbergen"
+
#: fdmprinter.def.json
msgctxt "z_seam_relative label"
msgid "Z Seam Relative"
@@ -1332,13 +1408,13 @@ msgstr "Bei Aktivierung sind die Z-Naht-Koordinaten relativ zur Mitte der jeweil
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic label"
-msgid "Ignore Small Z Gaps"
-msgstr "Schmale Z-Lücken ignorieren"
+msgid "No Skin in Z Gaps"
+msgstr "Keine Außenhaut in Z-Lücken"
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic description"
-msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
-msgstr "Wenn das Modell schmale vertikale Lücken hat, kann etwa 5 % zusätzliche Rechenzeit aufgewendet werden, um eine obere und untere Außenhaut in diesen engen Räumen zu generieren. In diesem Fall deaktivieren Sie die Einstellung."
+msgid "When the model has small vertical gaps of only a few layers, there should normally be skin around those layers in the narrow space. Enable this setting to not generate skin if the vertical gap is very small. This improves printing time and slicing time, but technically leaves infill exposed to the air."
+msgstr "Wenn das Modell kleine, nur wenige Schichten hohe vertikale Lücken aufweist, sind diese normalerweise von einer Außenhaut bedeckt. Aktivieren Sie diese Einstellung, damit bei sehr kleinen Lücken keine Außenhaut gedruckt wird. Dies verkürzt die zum Drucken und Slicen benötigte Zeit, aber die Füllung bleibt der Luft ausgesetzt."
#: fdmprinter.def.json
msgctxt "skin_outline_count label"
@@ -1357,8 +1433,8 @@ msgstr "Glätten aktivieren"
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
-msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
-msgstr "Gehen Sie ein weiteres Mal über die Oberfläche, jedoch ohne Extrusionsmaterial. Damit wird der Kunststoff auf der Oberfläche weiter geschmolzen, was zu einer glatteren Oberfläche führt."
+msgid "Go over the top surface one additional time, but this time extruding very little material. This is meant to melt the plastic on top further, creating a smoother surface. The pressure in the nozzle chamber is kept high so that the creases in the surface are filled with material."
+msgstr "Gehen Sie ein weiteres Mal über die Oberfläche, aber extrudieren Sie diesmal sehr wenig Material. Dadurch wird die oberste Kunststoffschicht geschmolzen und es entsteht eine glattere Oberfläche. Der Druck in der Düsenkammer bleibt weiterhin hoch, so dass Risse in der Oberfläche mit Material gefüllt werden."
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
@@ -1450,6 +1526,26 @@ msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
msgstr "Die maximale unmittelbare Geschwindigkeitsänderung während des Glättens."
+#: fdmprinter.def.json
+msgctxt "skin_overlap label"
+msgid "Skin Overlap Percentage"
+msgstr "Prozentsatz Außenhaut überlappen"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Justieren Sie die Überlappung zwischen den Wänden und den Außenhaut-Mittellinien bzw. den Endpunkten der Außenhaut-Mittellinien als Prozentwert der Linienbreite der Außenhautlinien und der inneren Wand. Eine geringe Überlappung ermöglicht die feste Verbindung der Wände mit der Außenhaut. Beachten Sie, dass bei einer einheitlichen Linienbreite von Außenhaut und Wand jeder Prozentwert über 50 % bereits dazu führen kann, dass die Außenhaut über die Wand hinausgeht, da in diesem Moment die Position der Düse des Außenhaut-Extruders möglicherweise bereits über die Wandmitte hinausgeht."
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm label"
+msgid "Skin Overlap"
+msgstr "Außenhaut überlappen"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Justieren Sie die Überlappung zwischen den Wänden und den Außenhaut-Mittellinien bzw. den Endpunkten der Außenhaut-Mittellinien. Eine geringe Überlappung ermöglicht die feste Verbindung der Wände mit der Außenhaut. Beachten Sie, dass bei einer einheitlichen Linienbreite von Außenhaut und Wand jeder Wert über die Hälfte der Wandbreite bereits dazu führen kann, dass die Außenhaut über die Wand hinausgeht, da in diesem Moment die Position der Düse des Außenhaut-Extruders möglicherweise bereits über die Wandmitte hinausgeht."
+
#: fdmprinter.def.json
msgctxt "infill label"
msgid "Infill"
@@ -1615,6 +1711,16 @@ msgctxt "infill_offset_y description"
msgid "The infill pattern is moved this distance along the Y axis."
msgstr "Das Füllmuster wird um diese Distanz entlang der Y-Achse verschoben."
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location label"
+msgid "Randomize Infill Start"
+msgstr "Füllstart randomisieren"
+
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location description"
+msgid "Randomize which infill line is printed first. This prevents one segment becoming the strongest, but it does so at the cost of an additional travel move."
+msgstr "Randomisieren Sie, welche Fülllinie zuerst gedruckt wird. So wird vermieden, dass ein Segment am stärksten ist. Allerdings muss dafür eine zusätzliche Bewegung ausgeführt werden."
+
#: fdmprinter.def.json
msgctxt "infill_multiplier label"
msgid "Infill Line Multiplier"
@@ -1669,26 +1775,6 @@ msgctxt "infill_overlap_mm description"
msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
msgstr "Das Ausmaß des Überlappens zwischen der Füllung und den Wänden. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Füllung herzustellen."
-#: fdmprinter.def.json
-msgctxt "skin_overlap label"
-msgid "Skin Overlap Percentage"
-msgstr "Prozentsatz Außenhaut überlappen"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm label"
-msgid "Skin Overlap"
-msgstr "Außenhaut überlappen"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "infill_wipe_dist label"
msgid "Infill Wipe Distance"
@@ -1869,6 +1955,16 @@ msgctxt "default_material_print_temperature description"
msgid "The default temperature used for printing. This should be the \"base\" temperature of a material. All other print temperatures should use offsets based on this value"
msgstr "Die für den Druck verwendete Standardtemperatur. Dies sollte die „Basis“-Temperatur eines Materials sein. Alle anderen Drucktemperaturen sollten anhand dieses Wertes einen Versatz verwenden"
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature label"
+msgid "Build Volume Temperature"
+msgstr "Temperatur Druckabmessung"
+
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature description"
+msgid "The temperature of the environment to print in. If this is 0, the build volume temperature will not be adjusted."
+msgstr "Die Temperatur der Druckumgebung. Beträgt der Wert 0, wird die Druckraumtemperatur nicht angepasst."
+
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
msgid "Printing Temperature"
@@ -1979,6 +2075,86 @@ msgctxt "material_shrinkage_percentage description"
msgid "Shrinkage ratio in percentage."
msgstr "Schrumpfungsverhältnis in Prozent."
+#: fdmprinter.def.json
+msgctxt "material_crystallinity label"
+msgid "Crystalline Material"
+msgstr "Kristallines Material"
+
+#: fdmprinter.def.json
+msgctxt "material_crystallinity description"
+msgid "Is this material the type that breaks off cleanly when heated (crystalline), or is it the type that produces long intertwined polymer chains (non-crystalline)?"
+msgstr "Lässt sich das Material im erhitzten Zustand leicht brechen (kristallin) oder bildet es lange, verflochtene Polymerketten (nicht kristallin)?"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position label"
+msgid "Anti-ooze Retracted Position"
+msgstr "Einzugsmaß für Sickerschutz"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position description"
+msgid "How far the material needs to be retracted before it stops oozing."
+msgstr "Maß, um das das Material eingezogen werden muss, damit es nicht heraussickert."
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed label"
+msgid "Anti-ooze Retraction Speed"
+msgstr "Einzugsgeschwindigkeit für Sickerschutz"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed description"
+msgid "How fast the material needs to be retracted during a filament switch to prevent oozing."
+msgstr "Geschwindigkeit, mit der das Material beim Filamentwechsel eingezogen werden muss, damit es nicht heraussickert."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position label"
+msgid "Break Preparation Retracted Position"
+msgstr "Einzugsmaß für Bruchvorbereitung"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position description"
+msgid "How far the filament can be stretched before it breaks, while heated."
+msgstr "Streckmaß für das Filament im erhitzten Zustand, bevor es bricht."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed label"
+msgid "Break Preparation Retraction Speed"
+msgstr "Einzugsgeschwindigkeit für Bruchvorbereitung"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed description"
+msgid "How fast the filament needs to be retracted just before breaking it off in a retraction."
+msgstr "Geschwindigkeit, mit der das Filament eingezogen werden muss, bevor es beim Einziehen abgebrochen wird."
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position label"
+msgid "Break Retracted Position"
+msgstr "Einzugsmaß für das Brechen"
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position description"
+msgid "How far to retract the filament in order to break it cleanly."
+msgstr "Maß, um das das Filament eingezogen werden muss, damit es sauber abgebrochen werden kann."
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed label"
+msgid "Break Retraction Speed"
+msgstr "Einzugsgeschwindigkeit für das Brechen"
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed description"
+msgid "The speed at which to retract the filament in order to break it cleanly."
+msgstr "Geschwindigkeit, mit der das Filament eingezogen werden muss, damit es sauber abgebrochen werden kann."
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature label"
+msgid "Break Temperature"
+msgstr "Bruchtemperatur"
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature description"
+msgid "The temperature at which the filament is broken for a clean break."
+msgstr "Die Temperatur, bei der das Filament für eine saubere Bruchstelle gebrochen wird."
+
#: fdmprinter.def.json
msgctxt "material_flow label"
msgid "Flow"
@@ -1989,6 +2165,126 @@ msgctxt "material_flow description"
msgid "Flow compensation: the amount of material extruded is multiplied by this value."
msgstr "Fluss-Kompensation: Die extrudierte Materialmenge wird mit diesem Wert multipliziert."
+#: fdmprinter.def.json
+msgctxt "wall_material_flow label"
+msgid "Wall Flow"
+msgstr "Wandfluss"
+
+#: fdmprinter.def.json
+msgctxt "wall_material_flow description"
+msgid "Flow compensation on wall lines."
+msgstr "Durchflusskompensation an Wandlinien."
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow label"
+msgid "Outer Wall Flow"
+msgstr "Wandfluss außen"
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow description"
+msgid "Flow compensation on the outermost wall line."
+msgstr "Durchflusskompensation an der äußeren Wandlinie."
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow label"
+msgid "Inner Wall(s) Flow"
+msgstr "Wandfluss innen"
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow description"
+msgid "Flow compensation on wall lines for all wall lines except the outermost one."
+msgstr "Durchflusskompensation an allen Wandlinien bis auf die äußere."
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow label"
+msgid "Top/Bottom Flow"
+msgstr "Fluss oben/unten"
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow description"
+msgid "Flow compensation on top/bottom lines."
+msgstr "Durchflusskompensation an oberen/unteren Linien."
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow label"
+msgid "Top Surface Skin Flow"
+msgstr "Fluss Oberfläche Außenhaut"
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow description"
+msgid "Flow compensation on lines of the areas at the top of the print."
+msgstr "Durchflusskompensation an Linien von Flächen an der Oberseite des Druckobjekts."
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow label"
+msgid "Infill Flow"
+msgstr "Fluss der Füllung"
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow description"
+msgid "Flow compensation on infill lines."
+msgstr "Durchflusskompensation an Füllungslinien."
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow label"
+msgid "Skirt/Brim Flow"
+msgstr "Skirt/Brim-Fluss"
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow description"
+msgid "Flow compensation on skirt or brim lines."
+msgstr "Durchflusskompensation an Skirt- oder Brim-Linien."
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow label"
+msgid "Support Flow"
+msgstr "Stützstruktur-Fluss"
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow description"
+msgid "Flow compensation on support structure lines."
+msgstr "Durchflusskompensation an Stützstrukturlinien."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow label"
+msgid "Support Interface Flow"
+msgstr "Fluss Stützstruktur-Schnittstelle"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow description"
+msgid "Flow compensation on lines of support roof or floor."
+msgstr "Durchflusskompensation an Dach- oder Bodenlinien der Stützstruktur."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow label"
+msgid "Support Roof Flow"
+msgstr "Stützdachfluss"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow description"
+msgid "Flow compensation on support roof lines."
+msgstr "Durchflusskompensation an Stützdachlinien."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow label"
+msgid "Support Floor Flow"
+msgstr "Stützbodenfluss"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow description"
+msgid "Flow compensation on support floor lines."
+msgstr "Durchflusskompensation an Stützbodenlinien."
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow label"
+msgid "Prime Tower Flow"
+msgstr "Fluss Einzugsturm"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow description"
+msgid "Flow compensation on prime tower lines."
+msgstr "Durchflusskompensation an Einzugsturmlinien."
+
#: fdmprinter.def.json
msgctxt "material_flow_layer_0 label"
msgid "Initial Layer Flow"
@@ -2106,7 +2402,7 @@ msgstr "Stützstruktur-Einzüge einschränken"
#: fdmprinter.def.json
msgctxt "limit_support_retractions description"
-msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure."
msgstr "Lassen Sie den Einzug beim Vorgehen von Stützstruktur zu Stützstruktur in einer geraden Linie aus. Die Aktivierung dieser Einstellung spart Druckzeit, kann jedoch zu übermäßigem Fadenziehen innerhalb der Stützstruktur führen."
#: fdmprinter.def.json
@@ -2127,7 +2423,7 @@ msgstr "Düsenschalter Einzugsabstand"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
msgid "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr ""
+msgstr "Der Wert für den Einzug beim Umstellen der Extruder: 0 einstellen, um keinen Einzug zu erhalten. Dies sollte generell mit der Länge der Heizzone übereinstimmen."
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_speeds label"
@@ -2159,6 +2455,16 @@ msgctxt "switch_extruder_prime_speed description"
msgid "The speed at which the filament is pushed back after a nozzle switch retraction."
msgstr "Die Geschwindigkeit, mit der das Filament während eines Düsenschaltereinzugs zurückgeschoben wird."
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount label"
+msgid "Nozzle Switch Extra Prime Amount"
+msgstr "Zusätzliche Einzugsmenge bei Düsenwechsel"
+
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount description"
+msgid "Extra material to prime after nozzle switching."
+msgstr "Nach einem Düsenwechsel zusätzlich bereitzustellendes Material."
+
#: fdmprinter.def.json
msgctxt "speed label"
msgid "Speed"
@@ -2350,14 +2656,14 @@ msgid "The speed at which the skirt and brim are printed. Normally this is done
msgstr "Die Geschwindigkeit, mit der die Skirt- und Brim-Elemente gedruckt werden. Normalerweise wird dafür die Geschwindigkeit der Basisschicht verwendet. In machen Fällen kann es jedoch vorteilhaft sein, das Skirt- oder Brim-Element mit einer anderen Geschwindigkeit zu drucken."
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override label"
-msgid "Maximum Z Speed"
-msgstr "Maximale Z-Geschwindigkeit"
+msgctxt "speed_z_hop label"
+msgid "Z Hop Speed"
+msgstr "Sprunghöhe Z"
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override description"
-msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
-msgstr "Die maximale Geschwindigkeit, mit der die Druckplatte bewegt wird. Eine Einstellung auf Null veranlasst die Verwendung der Firmware-Grundeinstellungen für die maximale Z-Geschwindigkeit."
+msgctxt "speed_z_hop description"
+msgid "The speed at which the vertical Z movement is made for Z Hops. This is typically lower than the print speed since the build plate or machine's gantry is harder to move."
+msgstr "Die Geschwindigkeit, mit der bei Z-Sprüngen die vertikale Bewegung (Z-Achse) erfolgt. Diese liegt in der Regel unterhalb der Druckgeschwindigkeit, da die Bewegung von Druckbett oder Brücke schwieriger ist."
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers label"
@@ -2787,7 +3093,7 @@ msgstr "Combing-Modus"
#: fdmprinter.def.json
msgctxt "retraction_combing description"
msgid "Combing keeps the nozzle within already printed areas when traveling. This results in slightly longer travel moves but reduces the need for retractions. If combing is off, the material will retract and the nozzle moves in a straight line to the next point. It is also possible to avoid combing over top/bottom skin areas or to only comb within the infill."
-msgstr ""
+msgstr "Durch Combing bleibt die Düse während der Bewegung innerhalb von bereits gedruckten Bereichen. Dies führt zu einer leicht verlängerten Bewegungszeit, reduziert jedoch die Notwendigkeit von Einzügen. Wenn Combing deaktiviert ist, wird das Material eingezogen und die Düse bewegt sich in einer geraden Linie zum nächsten Punkt. Es ist außerdem möglich, das Combing über die oberen/unteren Außenhautbereiche zu vermeiden, oder nur Combing innerhalb der Füllung auszuführen."
#: fdmprinter.def.json
msgctxt "retraction_combing option off"
@@ -2859,16 +3165,6 @@ msgctxt "travel_avoid_distance description"
msgid "The distance between the nozzle and already printed parts when avoiding during travel moves."
msgstr "Der Abstand zwischen der Düse und den bereits gedruckten Teilen, wenn diese bei Bewegungen umgangen werden."
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position label"
-msgid "Start Layers with the Same Part"
-msgstr "Startet Schichten mit demselben Teil"
-
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position description"
-msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
-msgstr "Beginnen Sie in jeder Schicht mit dem Drucken des Objekts in der Nähe desselben Punkts, sodass keine neue Schicht begonnen wird, wenn das Teil gedruckt wird, mit dem die letzte Schicht geendet hat. Damit lassen sich Überhänge und kleine Teile besser herstellen, allerdings verlängert sich die Druckzeit."
-
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
@@ -2929,6 +3225,16 @@ msgctxt "retraction_hop_after_extruder_switch description"
msgid "After the machine switched from one extruder to the other, the build plate is lowered to create clearance between the nozzle and the print. This prevents the nozzle from leaving oozed material on the outside of a print."
msgstr "Nachdem das Gerät von einem Extruder zu einem anderen geschaltet hat, wird die Druckplatte abgesenkt, um einen Abstand zwischen der Düse und dem Druck zu bilden. Das verhindert, dass die Düse abgesondertes Material auf der Außenseite des Drucks hinterlässt."
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height label"
+msgid "Z Hop After Extruder Switch Height"
+msgstr "Z-Sprung nach Extruder-Schalterhöhe"
+
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height description"
+msgid "The height difference when performing a Z Hop after extruder switch."
+msgstr "Der Höhenunterschied bei Ausführung eines Z-Sprungs nach Extruder-Schalter."
+
#: fdmprinter.def.json
msgctxt "cooling label"
msgid "Cooling"
@@ -3199,6 +3505,11 @@ msgctxt "support_pattern option cross"
msgid "Cross"
msgstr "Quer"
+#: fdmprinter.def.json
+msgctxt "support_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Gyroid"
+
#: fdmprinter.def.json
msgctxt "support_wall_count label"
msgid "Support Wall Line Count"
@@ -3260,14 +3571,14 @@ msgid "Distance between the printed initial layer support structure lines. This
msgstr "Der Abstand zwischen der ursprünglichen gedruckten Stützstrukturlinien. Diese Einstellung wird anhand der Dichte der Stützstruktur berechnet."
#: fdmprinter.def.json
-msgctxt "support_infill_angle label"
-msgid "Support Infill Line Direction"
+msgctxt "support_infill_angles label"
+msgid "Support Infill Line Directions"
msgstr "Unterstützung Linienrichtung Füllung"
#: fdmprinter.def.json
-msgctxt "support_infill_angle description"
-msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
-msgstr "Ausrichtung des Füllmusters für Unterstützung. Das Füllmuster für Unterstützung wird in der horizontalen Planfläche gedreht."
+msgctxt "support_infill_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees."
+msgstr "Liste der zu verwendenden Linienrichtungen (in ganzen Zahlen). Die Elemente der Liste werden während des Aufbaus der Schichten der Reihe nach abgearbeitet. Wenn das Ende der Liste erreicht wird, wird wieder beim ersten Element begonnen. Die Listenobjekte werden durch Kommas getrennt und die gesamte Liste ist in eckige Klammern gesetzt. Standardmäßig ist eine leere Liste vorhanden, was bedeutet, dass der Standardwinkel von 0 Grad zu verwenden ist."
#: fdmprinter.def.json
msgctxt "support_brim_enable label"
@@ -3396,8 +3707,8 @@ msgstr "Abstand für Zusammenführung der Stützstrukturen"
#: fdmprinter.def.json
msgctxt "support_join_distance description"
-msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
-msgstr "Der Maximalabstand zwischen Stützstrukturen in der X- und Y-Richtung. Wenn sich einzelne Strukturen näher aneinander befinden, als dieser Wert, werden diese Strukturen in eine einzige Struktur zusammengefügt."
+msgid "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one."
+msgstr "Der Maximalabstand zwischen Stützstrukturen in der X- und Y-Richtung. Wenn der Abstand einzelner Strukturen zueinander diesen Wert unterschreitet, werden diese Strukturen miteinander kombiniert und bilden eine Struktur."
#: fdmprinter.def.json
msgctxt "support_offset label"
@@ -3442,12 +3753,12 @@ msgstr "Die Höhe der Stützstruktur-Füllung einer bestimmten Dichte vor dem Um
#: fdmprinter.def.json
msgctxt "minimum_support_area label"
msgid "Minimum Support Area"
-msgstr ""
+msgstr "Mindestbereich Stützstruktur"
#: fdmprinter.def.json
msgctxt "minimum_support_area description"
msgid "Minimum area size for support polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgstr "Mindestflächenbreite für Stützstruktur-Polygone. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
#: fdmprinter.def.json
msgctxt "support_interface_enable label"
@@ -3677,62 +3988,93 @@ msgstr "Zickzack"
#: fdmprinter.def.json
msgctxt "minimum_interface_area label"
msgid "Minimum Support Interface Area"
-msgstr ""
+msgstr "Mindestbereich Stützstruktur-Schnittstelle"
#: fdmprinter.def.json
msgctxt "minimum_interface_area description"
-msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Mindestflächenbreite für Stützstruktur-Schnittstellen-Polygone. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden als normale Stützstruktur"
+" gedruckt."
#: fdmprinter.def.json
msgctxt "minimum_roof_area label"
msgid "Minimum Support Roof Area"
-msgstr ""
+msgstr "Mindestbereich Stützstrukturdach"
#: fdmprinter.def.json
msgctxt "minimum_roof_area description"
-msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Mindestfläche für die Dächer der Stützstruktur. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden als normale Stützstruktur gedruckt."
#: fdmprinter.def.json
msgctxt "minimum_bottom_area label"
msgid "Minimum Support Floor Area"
-msgstr ""
+msgstr "Mindestbereich Stützstrukturboden"
#: fdmprinter.def.json
msgctxt "minimum_bottom_area description"
-msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Mindestfläche für die Dächer der Stützstruktur. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden als normale Stützstruktur gedruckt."
#: fdmprinter.def.json
msgctxt "support_interface_offset label"
msgid "Support Interface Horizontal Expansion"
-msgstr ""
+msgstr "Horizontale Erweiterung Stützstruktur-Schnittstelle"
#: fdmprinter.def.json
msgctxt "support_interface_offset description"
msgid "Amount of offset applied to the support interface polygons."
-msgstr ""
+msgstr "Umfang des angewandten Versatzes für die Stützstruktur-Schnittstellen-Polygone."
#: fdmprinter.def.json
msgctxt "support_roof_offset label"
msgid "Support Roof Horizontal Expansion"
-msgstr ""
+msgstr "Horizontale Erweiterung Stützstrukturdach"
#: fdmprinter.def.json
msgctxt "support_roof_offset description"
msgid "Amount of offset applied to the roofs of the support."
-msgstr ""
+msgstr "Umfang des angewandten Versatzes für die Dächer der Stützstruktur."
#: fdmprinter.def.json
msgctxt "support_bottom_offset label"
msgid "Support Floor Horizontal Expansion"
-msgstr ""
+msgstr "Horizontale Erweiterung Stützstrukturboden"
#: fdmprinter.def.json
msgctxt "support_bottom_offset description"
msgid "Amount of offset applied to the floors of the support."
-msgstr ""
+msgstr "Umfang des angewandten Versatzes für die Böden der Stützstruktur."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles label"
+msgid "Support Interface Line Directions"
+msgstr "Richtungen der Verbindungslinien unterstützen"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Liste der zu verwendenden Linienrichtungen (in ganzen Zahlen). Die Elemente der Liste werden während des Aufbaus der Schichten der Reihe nach abgearbeitet. Wenn das Ende der Liste erreicht wird, wird wieder beim ersten Element begonnen. Die Listenobjekte werden durch Kommas getrennt und die gesamte Liste ist in eckige Klammern gesetzt. Standardmäßig ist eine leere Liste vorhanden, was bedeutet, dass herkömmliche Standardwinkel (zwischen 45 und 135- rad, falls die Verbindungsstellen ziemlich dick sind, oder 90 Grad) zu verwenden sind."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles label"
+msgid "Support Roof Line Directions"
+msgstr "Richtungen der Dachlinien unterstützen"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Liste der zu verwendenden Linienrichtungen (in ganzen Zahlen). Die Elemente der Liste werden während des Aufbaus der Schichten der Reihe nach abgearbeitet. Wenn das Ende der Liste erreicht wird, wird wieder beim ersten Element begonnen. Die Listenobjekte werden durch Kommas getrennt und die gesamte Liste ist in eckige Klammern gesetzt. Standardmäßig ist eine leere Liste vorhanden, was bedeutet, dass herkömmliche Standardwinkel (zwischen 45 und 135- rad, falls die Verbindungsstellen ziemlich dick sind, oder 90 Grad) zu verwenden sind."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles label"
+msgid "Support Floor Line Directions"
+msgstr "Richtungen der Bodenlinien unterstützen"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Liste der zu verwendenden Linienrichtungen (in ganzen Zahlen). Die Elemente der Liste werden während des Aufbaus der Schichten der Reihe nach abgearbeitet. Wenn das Ende der Liste erreicht wird, wird wieder beim ersten Element begonnen. Die Listenobjekte werden durch Kommas getrennt und die gesamte Liste ist in eckige Klammern gesetzt. Standardmäßig ist eine leere Liste vorhanden, was bedeutet, dass herkömmliche Standardwinkel (zwischen 45 und 135- rad, falls die Verbindungsstellen ziemlich dick sind, oder 90 Grad) zu verwenden sind."
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
@@ -3775,13 +4117,13 @@ msgid "The diameter of a special tower."
msgstr "Der Durchmesser eines speziellen Pfeilers."
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter label"
-msgid "Minimum Diameter"
-msgstr "Mindestdurchmesser"
+msgctxt "support_tower_maximum_supported_diameter label"
+msgid "Maximum Tower-Supported Diameter"
+msgstr "Maximaler Durchmesser für Stützpfeiler"
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter description"
-msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+msgctxt "support_tower_maximum_supported_diameter description"
+msgid "Maximum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
msgstr "Der Mindestdurchmesser in den X/Y-Richtungen eines kleinen Bereichs, der durch einen speziellen Stützpfeiler gestützt wird."
#: fdmprinter.def.json
@@ -4278,16 +4620,6 @@ msgctxt "prime_tower_enable description"
msgid "Print a tower next to the print which serves to prime the material after each nozzle switch."
msgstr "Drucken Sie einen Turm neben dem Druck, der zum Einziehen des Materials nach jeder Düsenschaltung dient."
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular label"
-msgid "Circular Prime Tower"
-msgstr "Einzugsturm kreisförmig"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular description"
-msgid "Make the prime tower as a circular shape."
-msgstr "Macht den Einzugsturm zu einer Kreisform."
-
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
@@ -4328,16 +4660,6 @@ msgctxt "prime_tower_position_y description"
msgid "The y coordinate of the position of the prime tower."
msgstr "Die Y-Koordinate der Position des Einzugsturms."
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow label"
-msgid "Prime Tower Flow"
-msgstr "Fluss Einzugsturm"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow description"
-msgid "Flow compensation: the amount of material extruded is multiplied by this value."
-msgstr "Fluss-Kompensation: Die extrudierte Materialmenge wird mit diesem Wert multipliziert."
-
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
@@ -4348,6 +4670,16 @@ msgctxt "prime_tower_wipe_enabled description"
msgid "After printing the prime tower with one nozzle, wipe the oozed material from the other nozzle off on the prime tower."
msgstr "Nach dem Drucken des Einzugsturms mit einer Düse wird das ausgetretene Material von der anderen Düse am Einzugsturm abgewischt."
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable label"
+msgid "Prime Tower Brim"
+msgstr "Brim Einzugsturm"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable description"
+msgid "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type."
+msgstr "Einzugstürme benötigen möglicherweise zusätzliche Haftung in Form eines Brims, auch wenn das Modell selbst dies nicht benötigt. Kann derzeit nicht mit dem „Raft“-Haftungstyp verwendet werden."
+
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
msgid "Enable Ooze Shield"
@@ -4468,6 +4800,36 @@ msgctxt "remove_empty_first_layers description"
msgid "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle."
msgstr "Entfernen Sie die leeren Schichten unter der ersten gedruckten Schicht, sofern vorhanden. Die Deaktivierung dieser Einstellung kann zu leeren ersten Schichten führen, wenn die Einstellung der Slicing-Toleranz auf Exklusiv oder Mittel gesetzt wurde."
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Maximale Auflösung"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "Die Mindestgröße eines Linienabschnitts nach dem Slicen. Wenn Sie diesen Wert erhöhen, führt dies zu einer niedrigeren Auslösung des Mesh. Damit kann der Drucker die erforderliche Geschwindigkeit für die Verarbeitung des G-Codes beibehalten; außerdem wird die Slice-Geschwindigkeit erhöht, indem Details des Mesh entfernt werden, die ohnehin nicht verarbeitet werden können."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution label"
+msgid "Maximum Travel Resolution"
+msgstr "Maximale Bewegungsauflösung"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution description"
+msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
+msgstr "Die maximale Größe eines Bewegungsliniensegments nach dem Slicen. Wenn Sie diesen Wert erhöhen, weisen die Fahrtbewegungen weniger glatte Kanten aus. Das ermöglicht dem Drucker, die für die Verarbeitung eines G-Codes erforderliche Geschwindigkeit aufrechtzuerhalten, allerdings kann das Modell damit auch weniger akkurat werden."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation label"
+msgid "Maximum Deviation"
+msgstr "Maximale Abweichung"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation description"
+msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true."
+msgstr "Die maximal zulässige Abweichung bei Reduzierung der maximalen Auflösung. Wenn Sie diesen Wert erhöhen, wird der Druck ungenauer, der G-Code wird jedoch kleiner. Die maximale Abweichung ist eine Grenze für die maximale Auflösung. Wenn die beiden Werte sich widersprechen, wird stets die maximale Abweichung eingehalten."
+
#: fdmprinter.def.json
msgctxt "blackmagic label"
msgid "Special Modes"
@@ -4630,8 +4992,8 @@ msgstr "Spiralisieren der äußeren Konturen glätten"
#: fdmprinter.def.json
msgctxt "smooth_spiralized_contours description"
-msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
-msgstr "Glättet die spiralförmigen Konturen, um die Sichtbarkeit der Z-Naht zu reduzieren (die Z-Naht sollte auf dem Druck kaum sichtbar sein, ist jedoch in der Schichtenansicht erkennbar). Beachten Sie, dass das Glätten dazu neigt, feine Oberflächendetails zu verwischen."
+msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+msgstr "Glättet die spiralförmigen Konturen, um die Sichtbarkeit der Z-Naht zu reduzieren (die Z-Naht sollte am Druckobjekt kaum sichtbar sein, ist jedoch in der Schichtenansicht erkennbar). Beachten Sie, dass beim Glätten feine Oberflächendetails verwischt werden."
#: fdmprinter.def.json
msgctxt "relative_extrusion label"
@@ -4843,26 +5205,6 @@ msgctxt "minimum_polygon_circumference description"
msgid "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details."
msgstr "Polygone in geschnittenen Schichten, die einen Umfang unter diesem Wert haben, werden ausgefiltert. Niedrigere Werte führen zu einem Mesh mit höherer Auflösung zulasten der Slicing-Zeit. Dies gilt in erster Linie für SLA-Drucker mit höherer Auflösung und sehr kleine 3D-Modelle mit zahlreichen Details."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Maximale Auflösung"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "Die Mindestgröße eines Linienabschnitts nach dem Slicen. Wenn Sie diesen Wert erhöhen, führt dies zu einer niedrigeren Auslösung des Mesh. Damit kann der Drucker die erforderliche Geschwindigkeit für die Verarbeitung des G-Codes beibehalten; außerdem wird die Slice-Geschwindigkeit erhöht, indem Details des Mesh entfernt werden, die ohnehin nicht verarbeitet werden können."
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution label"
-msgid "Maximum Travel Resolution"
-msgstr "Maximale Bewegungsauflösung"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution description"
-msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
-msgstr "Die maximale Größe eines Bewegungsliniensegments nach dem Slicen. Wenn Sie diesen Wert erhöhen, weisen die Fahrtbewegungen weniger glatte Kanten aus. Das ermöglicht dem Drucker, die für die Verarbeitung eines G-Codes erforderliche Geschwindigkeit aufrechtzuerhalten, allerdings kann das Modell damit auch weniger akkurat werden."
-
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5003,16 +5345,6 @@ msgctxt "coasting_speed description"
msgid "The speed by which to move during coasting, relative to the speed of the extrusion path. A value slightly under 100% is advised, since during the coasting move the pressure in the bowden tube drops."
msgstr "Die Geschwindigkeit, mit der die Bewegung während des Coasting erfolgt, in Relation zur Geschwindigkeit des Extrusionswegs. Ein Wert leicht unter 100 % wird empfohlen, da während der Coasting-Bewegung der Druck in den Bowden-Röhren abfällt."
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation label"
-msgid "Alternate Skin Rotation"
-msgstr "Wechselnde Rotation der Außenhaut"
-
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation description"
-msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
-msgstr "Die Richtung, in welcher die oberen/unteren Schichten gedruckt werden, wird abgewechselt. Normalerweise werden diese nur diagonal gedruckt. Diese Einstellung fügt die Nur-X- und Nur-Y-Richtung zu."
-
#: fdmprinter.def.json
msgctxt "cross_infill_pocket_size label"
msgid "Cross 3D Pocket Size"
@@ -5120,8 +5452,8 @@ msgstr "Konische Stützstruktur aktivieren"
#: fdmprinter.def.json
msgctxt "support_conical_enabled description"
-msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
-msgstr "Experimentelle Funktion: Macht die Bereiche der Stützstruktur am Boden kleiner als beim Überhang."
+msgid "Make support areas smaller at the bottom than at the overhang."
+msgstr "Macht die Bereiche der Stützstruktur am Boden kleiner als beim Überhang."
#: fdmprinter.def.json
msgctxt "support_conical_angle label"
@@ -5185,23 +5517,24 @@ msgstr "Der durchschnittliche Abstand zwischen den willkürlich auf jedes Linien
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
-msgid "Flow rate compensation max extrusion offset"
+msgid "Flow Rate Compensation Max Extrusion Offset"
msgstr "Ausgleich Durchflussrate max. Extrusionswirkung"
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
-msgid "The maximum distance in mm to compensate."
-msgstr "Die maximale Distanz in mm für den Ausgleich."
+msgid "The maximum distance in mm to move the filament to compensate for changes in flow rate."
+msgstr "Die maximale Strecke (in mm), die das Filament bewegt werden kann, um Änderungen der Durchflussrate zu kompensieren."
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor label"
-msgid "Flow rate compensation factor"
+msgid "Flow Rate Compensation Factor"
msgstr "Ausgleichsfaktor Durchflussrate"
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor description"
-msgid "The multiplication factor for the flow rate -> distance translation."
-msgstr "Der Multiplikationsfaktor für die Übersetzung Durchflussrate -> Distanz."
+msgid "How far to move the filament in order to compensate for changes in flow rate, as a percentage of how far the filament would move in one second of extrusion."
+msgstr "Wie weit das Filament bewegt werden kann, um Änderungen der Durchflussrate zu kompensieren – als Prozentsatz der Strecke, die das Filament sich während"
+" einer Sekunde Extrusion bewegen würde."
#: fdmprinter.def.json
msgctxt "wireframe_enabled label"
@@ -5464,7 +5797,7 @@ msgstr "Der Abstand zwischen der Düse und den horizontalen Abwärtslinien. Bei
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr "Anpassschichten verwenden"
#: fdmprinter.def.json
@@ -5474,7 +5807,7 @@ msgstr "Die Funktion Anpassschichten berechnet die Schichthöhe je nach Form des
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation label"
-msgid "Adaptive layers maximum variation"
+msgid "Adaptive Layers Maximum Variation"
msgstr "Maximale Abweichung für Anpassschichten"
#: fdmprinter.def.json
@@ -5484,7 +5817,7 @@ msgstr "Die max. zulässige Höhendifferenz von der Basisschichthöhe."
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation_step label"
-msgid "Adaptive layers variation step size"
+msgid "Adaptive Layers Variation Step Size"
msgstr "Abweichung Schrittgröße für Anpassschichten"
#: fdmprinter.def.json
@@ -5494,13 +5827,14 @@ msgstr "Der Höhenunterscheid der nächsten Schichthöhe im Vergleich zur vorher
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
-msgstr "Schwellenwert Anpassschichten"
+msgid "Adaptive Layers Topography Size"
+msgstr "Topographische Größe der Anpassschichten"
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold description"
-msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
-msgstr "Das ist der Schwellenwert, der definiert, ob eine kleinere Schicht verwendet wird oder nicht. Dieser Wert wird mit dem der stärksten Neigung in einer Schicht verglichen."
+msgid "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together."
+msgstr "Horizontaler Abstand zwischen zwei angrenzenden Schichten. Bei Einstellung eines niedrigeren Werts werden dünnere Schichten aufgetragen, damit die Kanten"
+" der Schichten enger aneinander liegen."
#: fdmprinter.def.json
msgctxt "wall_overhang_angle label"
@@ -5509,8 +5843,9 @@ msgstr "Winkel für überhängende Wände"
#: fdmprinter.def.json
msgctxt "wall_overhang_angle description"
-msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
-msgstr "Wände, die über diesen Winkel hinaus hängen, werden mithilfe der Einstellungen für Winkel für überhängende Wände gedruckt. Wenn der Wert 90 beträgt, werden keine Wände als überhängend behandelt."
+msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging. Overhang that gets supported by support will not be treated as overhang either."
+msgstr "Wände, die über diesen Winkel hinaus hängen, werden mithilfe der Einstellungen für Winkel für überhängende Wände gedruckt. Wenn der Wert 90 beträgt, werden"
+" keine Wände als überhängend behandelt. Überhänge, die von Stützstrukturen gestützt werden, werden ebenfalls nicht als Überhang behandelt."
#: fdmprinter.def.json
msgctxt "wall_overhang_speed_factor label"
@@ -5712,6 +6047,198 @@ msgctxt "bridge_fan_speed_3 description"
msgid "Percentage fan speed to use when printing the third bridge skin layer."
msgstr "Prozentwert der Lüfterdrehzahl für das Drucken der dritten Brücken-Außenhautschicht."
+#: fdmprinter.def.json
+msgctxt "clean_between_layers label"
+msgid "Wipe Nozzle Between Layers"
+msgstr "Düse zwischen den Schichten abwischen"
+
+#: fdmprinter.def.json
+msgctxt "clean_between_layers description"
+msgid "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working."
+msgstr "Option für das Einfügen eines G-Codes für das Abwischen der Düse zwischen den Schichten. Die Aktivierung dieser Einstellung könnte das Einzugsverhalten beim Schichtenwechsel beeinflussen. Verwenden Sie bitte die Einstellungen für Abwischen bei Einzug, um das Einziehen bei Schichten zu steuern, bei denen das Skript für Wischen aktiv wird."
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe label"
+msgid "Material Volume Between Wipes"
+msgstr "Materialmenge zwischen den Wischvorgängen"
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe description"
+msgid "Maximum material, that can be extruded before another nozzle wipe is initiated."
+msgstr "Die maximale Materialmenge, die extrudiert werden kann, bevor die Düse ein weiteres Mal abgewischt wird."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable label"
+msgid "Wipe Retraction Enable"
+msgstr "Abwischen bei Einzug aktivieren"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable description"
+msgid "Retract the filament when the nozzle is moving over a non-printed area."
+msgstr "Das Filament wird eingezogen, wenn sich die Düse über einen nicht zu bedruckenden Bereich bewegt."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount label"
+msgid "Wipe Retraction Distance"
+msgstr "Einzugsabstand für Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount description"
+msgid "Amount to retract the filament so it does not ooze during the wipe sequence."
+msgstr "Wert, um den das Filament eingezogen wird, damit es während des Abwischens nicht austritt."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount label"
+msgid "Wipe Retraction Extra Prime Amount"
+msgstr "Zusätzliche Zurückschiebemenge nach Einzug für Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount description"
+msgid "Some material can ooze away during a wipe travel moves, which can be compensated for here."
+msgstr "Während einer Bewegung für den Abwischvorgang kann Material wegsickern, was hier kompensiert werden kann."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed label"
+msgid "Wipe Retraction Speed"
+msgstr "Einzugsgeschwindigkeit für Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed description"
+msgid "The speed at which the filament is retracted and primed during a wipe retraction move."
+msgstr "Die Geschwindigkeit, mit der das Filament während einer Einzugsbewegung eingezogen und während einer Einzugsbewegung für Abwischen zurückgeschoben wird."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed label"
+msgid "Wipe Retraction Retract Speed"
+msgstr "Einzugsgeschwindigkeit (Einzug) für Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed description"
+msgid "The speed at which the filament is retracted during a wipe retraction move."
+msgstr "Die Geschwindigkeit, mit der das Filament während einer Einzugsbewegung für Abwischen eingezogen wird."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed label"
+msgid "Retraction Prime Speed"
+msgstr "Einzugsgeschwindigkeit (Einzug)"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed description"
+msgid "The speed at which the filament is primed during a wipe retraction move."
+msgstr "Die Geschwindigkeit, mit der das Filament während einer Einzugsbewegung vorbereitet wird."
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause label"
+msgid "Wipe Pause"
+msgstr "Abwischen pausieren"
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause description"
+msgid "Pause after the unretract."
+msgstr "Pausieren nach Aufhebung des Einzugs."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable label"
+msgid "Wipe Z Hop When Retracted"
+msgstr "Z-Sprung beim Einziehen - Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable description"
+msgid "Whenever a retraction is done, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate."
+msgstr "Nach dem Einzug wird das Druckbett gesenkt, um einen Abstand zwischen Düse und Druck herzustellen. Das verhindert, dass die Düse den Druck während der Bewegungen anschlägt und verringert die Möglichkeit, dass der Druck vom Druckbett heruntergestoßen wird."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount label"
+msgid "Wipe Z Hop Height"
+msgstr "Z-Sprung Höhe - Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount description"
+msgid "The height difference when performing a Z Hop."
+msgstr "Der Höhenunterschied bei Ausführung eines Z-Sprungs."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed label"
+msgid "Wipe Hop Speed"
+msgstr "Sprunghöhe - Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed description"
+msgid "Speed to move the z-axis during the hop."
+msgstr "Geschwindigkeit für das Verfahren der Z-Achse während des Sprungs."
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x label"
+msgid "Wipe Brush X Position"
+msgstr "X-Position für Bürste - Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x description"
+msgid "X location where wipe script will start."
+msgstr "X-Position, an der das Skript für Abwischen startet."
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count label"
+msgid "Wipe Repeat Count"
+msgstr "Wiederholungszähler - Abwischen"
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count description"
+msgid "Number of times to move the nozzle across the brush."
+msgstr "Anzahl der Wiederholungen für das Bewegen der Düse über der Bürste."
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance label"
+msgid "Wipe Move Distance"
+msgstr "Abstand Wischbewegung"
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance description"
+msgid "The distance to move the head back and forth across the brush."
+msgstr "Die Strecke, die der Kopf durch Vorwärts- und Rückwärtsbewegung über die Bürste hinweg fährt."
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size label"
+msgid "Small Hole Max Size"
+msgstr "Max. Lochdurchmesser"
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size description"
+msgid "Holes and part outlines with a diameter smaller than this will be printed using Small Feature Speed."
+msgstr "Löcher und Teilkonturen mit einem kleineren Durchmesser werden mit Small Feature Speed gedruckt."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length label"
+msgid "Small Feature Max Length"
+msgstr "Max. Detaillänge"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length description"
+msgid "Feature outlines that are shorter than this length will be printed using Small Feature Speed."
+msgstr "Teile, die kleiner sind als dieser Wert, werden in Detailgeschwindigkeit gedruckt."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor label"
+msgid "Small Feature Speed"
+msgstr "Detailgeschwindigkeit"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor description"
+msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "Bei kleinen Details wird die Geschwindigkeit auf diesen Prozentsatz der normalen Druckgeschwindigkeit gesetzt. Durch eine niedrigere Druckgeschwindigkeit"
+" können die Haftung und die Genauigkeit verbessert werden."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 label"
+msgid "Small Feature Initial Layer Speed"
+msgstr "Geschwindigkeit der ersten Schicht von Details"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 description"
+msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "Bei kleinen Details wird die Geschwindigkeit bei der ersten Schicht auf diesen Prozentsatz der normalen Druckgeschwindigkeit gesetzt. Durch eine niedrigere"
+" Druckgeschwindigkeit können die Haftung und die Genauigkeit verbessert werden."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5772,6 +6299,218 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Transformationsmatrix, die beim Laden aus der Datei auf das Modell angewandt wird."
+#~ msgctxt "minimum_interface_area description"
+#~ msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Mindestflächenbreite für Stützstruktur-Schnittstellen-Polygone. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
+
+#~ msgctxt "minimum_roof_area description"
+#~ msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Mindestflächenbreite für die Dächer der Stützstruktur. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
+
+#~ msgctxt "minimum_bottom_area description"
+#~ msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Mindestflächenbreite für die Böden der Stützstruktur. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
+
+#~ msgctxt "skin_alternate_rotation label"
+#~ msgid "Alternate Skin Rotation"
+#~ msgstr "Wechselnde Rotation der Außenhaut"
+
+#~ msgctxt "skin_alternate_rotation description"
+#~ msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
+#~ msgstr "Die Richtung, in welcher die oberen/unteren Schichten gedruckt werden, wird abgewechselt. Normalerweise werden diese nur diagonal gedruckt. Diese Einstellung fügt die Nur-X- und Nur-Y-Richtung zu."
+
+#~ msgctxt "flow_rate_max_extrusion_offset label"
+#~ msgid "Flow rate compensation max extrusion offset"
+#~ msgstr "Ausgleich Durchflussrate max. Extrusionswirkung"
+
+#~ msgctxt "flow_rate_max_extrusion_offset description"
+#~ msgid "The maximum distance in mm to compensate."
+#~ msgstr "Die maximale Distanz in mm für den Ausgleich."
+
+#~ msgctxt "flow_rate_extrusion_offset_factor label"
+#~ msgid "Flow rate compensation factor"
+#~ msgstr "Ausgleichsfaktor Durchflussrate"
+
+#~ msgctxt "flow_rate_extrusion_offset_factor description"
+#~ msgid "The multiplication factor for the flow rate -> distance translation."
+#~ msgstr "Der Multiplikationsfaktor für die Übersetzung Durchflussrate -> Distanz."
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive Layers Threshold"
+#~ msgstr "Schwellenwert Anpassschichten"
+
+#~ msgctxt "adaptive_layer_height_threshold description"
+#~ msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+#~ msgstr "Das ist der Schwellenwert, der definiert, ob eine kleinere Schicht verwendet wird oder nicht. Dieser Wert wird mit dem der stärksten Neigung in einer Schicht verglichen."
+
+#~ msgctxt "wall_overhang_angle description"
+#~ msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
+#~ msgstr "Wände, die über diesen Winkel hinaus hängen, werden mithilfe der Einstellungen für Winkel für überhängende Wände gedruckt. Wenn der Wert 90 beträgt, werden keine Wände als überhängend behandelt."
+
+#~ msgctxt "small_feature_speed_factor description"
+#~ msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "Bei kleinen Details wird die Geschwindigkeit auf diesen Prozentsatz der normalen Druckgeschwindigkeit gesetzt. Durch eine niedrigere Druckgeschwindigkeit kann die Haftung und die Genauigkeit verbessert werden."
+
+#~ msgctxt "small_feature_speed_factor_0 label"
+#~ msgid "First Layer Speed"
+#~ msgstr "Geschwindigkeit für erste Schicht"
+
+#~ msgctxt "small_feature_speed_factor_0 description"
+#~ msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "Bei kleinen Details wird die Geschwindigkeit bei der ersten Schicht auf diesen Prozentsatz der normalen Druckgeschwindigkeit gesetzt. Durch eine niedrigere Druckgeschwindigkeit kann die Haftung und die Genauigkeit verbessert werden."
+
+#~ msgctxt "ironing_enabled description"
+#~ msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
+#~ msgstr "Gehen Sie ein weiteres Mal über die Oberfläche, jedoch ohne Extrusionsmaterial. Damit wird der Kunststoff auf der Oberfläche weiter geschmolzen, was zu einer glatteren Oberfläche führt."
+
+#~ msgctxt "start_layers_at_same_position label"
+#~ msgid "Start Layers with the Same Part"
+#~ msgstr "Startet Schichten mit demselben Teil"
+
+#~ msgctxt "start_layers_at_same_position description"
+#~ msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
+#~ msgstr "Beginnen Sie in jeder Schicht mit dem Drucken des Objekts in der Nähe desselben Punkts, sodass keine neue Schicht begonnen wird, wenn das Teil gedruckt wird, mit dem die letzte Schicht geendet hat. Damit lassen sich Überhänge und kleine Teile besser herstellen, allerdings verlängert sich die Druckzeit."
+
+#~ msgctxt "support_infill_angles description"
+#~ msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
+#~ msgstr "Ausrichtung des Füllmusters für Unterstützung. Das Füllmuster für Unterstützung wird in der horizontalen Planfläche gedreht."
+
+#~ msgctxt "meshfix_maximum_deviation description"
+#~ msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller."
+#~ msgstr "Die maximal zulässige Abweichung bei Reduzierung der Auflösung für die Einstellung der maximalen Auflösung. Wenn Sie diesen Wert erhöhen, wird der Druck ungenauer, der G-Code wird jedoch kleiner."
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code Flavour"
+#~ msgstr "G-Code-Variante"
+
+#~ msgctxt "z_seam_corner description"
+#~ msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
+#~ msgstr "Definieren Sie, ob Kanten am Modell-Umriss die Nahtposition beeinflussen. Keine bedeutet, dass Kanten keinen Einfluss auf die Nahtposition haben. Naht verbergen lässt die Naht mit höherer Wahrscheinlichkeit an einer innenliegenden Kante auftreten. Naht offenlegen lässt die Naht mit höherer Wahrscheinlichkeit an einer Außenkante auftreten. Naht verbergen oder offenlegen lässt die Naht mit höherer Wahrscheinlichkeit an einer innenliegenden oder außenliegenden Kante auftreten."
+
+#~ msgctxt "skin_no_small_gaps_heuristic label"
+#~ msgid "Ignore Small Z Gaps"
+#~ msgstr "Schmale Z-Lücken ignorieren"
+
+#~ msgctxt "skin_no_small_gaps_heuristic description"
+#~ msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
+#~ msgstr "Wenn das Modell schmale vertikale Lücken hat, kann etwa 5 % zusätzliche Rechenzeit aufgewendet werden, um eine obere und untere Außenhaut in diesen engen Räumen zu generieren. In diesem Fall deaktivieren Sie die Einstellung."
+
+#~ msgctxt "build_volume_temperature description"
+#~ msgid "The temperature used for build volume. If this is 0, the build volume temperature will not be adjusted."
+#~ msgstr "Die für die Druckabmessung verwendete Temperatur. Wenn dieser Wert 0 beträgt, wird die Temperatur der Druckabmessung nicht angepasst."
+
+#~ msgctxt "limit_support_retractions description"
+#~ msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+#~ msgstr "Lassen Sie den Einzug beim Vorgehen von Stützstruktur zu Stützstruktur in einer geraden Linie aus. Die Aktivierung dieser Einstellung spart Druckzeit, kann jedoch zu übermäßigem Fadenziehen innerhalb der Stützstruktur führen."
+
+#~ msgctxt "max_feedrate_z_override label"
+#~ msgid "Maximum Z Speed"
+#~ msgstr "Maximale Z-Geschwindigkeit"
+
+#~ msgctxt "max_feedrate_z_override description"
+#~ msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
+#~ msgstr "Die maximale Geschwindigkeit, mit der die Druckplatte bewegt wird. Eine Einstellung auf Null veranlasst die Verwendung der Firmware-Grundeinstellungen für die maximale Z-Geschwindigkeit."
+
+#~ msgctxt "support_join_distance description"
+#~ msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
+#~ msgstr "Der Maximalabstand zwischen Stützstrukturen in der X- und Y-Richtung. Wenn sich einzelne Strukturen näher aneinander befinden, als dieser Wert, werden diese Strukturen in eine einzige Struktur zusammengefügt."
+
+#~ msgctxt "support_minimal_diameter label"
+#~ msgid "Minimum Diameter"
+#~ msgstr "Mindestdurchmesser"
+
+#~ msgctxt "support_minimal_diameter description"
+#~ msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+#~ msgstr "Der Mindestdurchmesser in den X/Y-Richtungen eines kleinen Bereichs, der durch einen speziellen Stützpfeiler gestützt wird."
+
+#~ msgctxt "prime_tower_circular label"
+#~ msgid "Circular Prime Tower"
+#~ msgstr "Einzugsturm kreisförmig"
+
+#~ msgctxt "prime_tower_circular description"
+#~ msgid "Make the prime tower as a circular shape."
+#~ msgstr "Macht den Einzugsturm zu einer Kreisform."
+
+#~ msgctxt "prime_tower_flow description"
+#~ msgid "Flow compensation: the amount of material extruded is multiplied by this value."
+#~ msgstr "Fluss-Kompensation: Die extrudierte Materialmenge wird mit diesem Wert multipliziert."
+
+#~ msgctxt "smooth_spiralized_contours description"
+#~ msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+#~ msgstr "Glättet die spiralförmigen Konturen, um die Sichtbarkeit der Z-Naht zu reduzieren (die Z-Naht sollte auf dem Druck kaum sichtbar sein, ist jedoch in der Schichtenansicht erkennbar). Beachten Sie, dass das Glätten dazu neigt, feine Oberflächendetails zu verwischen."
+
+#~ msgctxt "support_conical_enabled description"
+#~ msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
+#~ msgstr "Experimentelle Funktion: Macht die Bereiche der Stützstruktur am Boden kleiner als beim Überhang."
+
+#~ msgctxt "extruders_enabled_count label"
+#~ msgid "Number of Extruders that are enabled"
+#~ msgstr "Anzahl der aktivierten Extruder"
+
+#~ msgctxt "machine_nozzle_tip_outer_diameter label"
+#~ msgid "Outer nozzle diameter"
+#~ msgstr "Düsendurchmesser außen"
+
+#~ msgctxt "machine_nozzle_head_distance label"
+#~ msgid "Nozzle length"
+#~ msgstr "Düsenlänge"
+
+#~ msgctxt "machine_nozzle_expansion_angle label"
+#~ msgid "Nozzle angle"
+#~ msgstr "Düsenwinkel"
+
+#~ msgctxt "machine_heat_zone_length label"
+#~ msgid "Heat zone length"
+#~ msgstr "Heizzonenlänge"
+
+#~ msgctxt "machine_nozzle_heat_up_speed label"
+#~ msgid "Heat up speed"
+#~ msgstr "Aufheizgeschwindigkeit"
+
+#~ msgctxt "machine_nozzle_cool_down_speed label"
+#~ msgid "Cool down speed"
+#~ msgstr "Abkühlgeschwindigkeit"
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code flavour"
+#~ msgstr "G-Code-Variante"
+
+#~ msgctxt "machine_disallowed_areas label"
+#~ msgid "Disallowed areas"
+#~ msgstr "Unzulässige Bereiche"
+
+#~ msgctxt "machine_head_polygon label"
+#~ msgid "Machine head polygon"
+#~ msgstr "Gerätekopf Polygon"
+
+#~ msgctxt "machine_head_with_fans_polygon label"
+#~ msgid "Machine head & Fan polygon"
+#~ msgstr "Gerätekopf und Lüfter Polygon"
+
+#~ msgctxt "gantry_height label"
+#~ msgid "Gantry height"
+#~ msgstr "Brückenhöhe"
+
+#~ msgctxt "machine_use_extruder_offset_to_offset_coords label"
+#~ msgid "Offset With Extruder"
+#~ msgstr "Versatz mit Extruder"
+
+#~ msgctxt "adaptive_layer_height_enabled label"
+#~ msgid "Use adaptive layers"
+#~ msgstr "Anpassschichten verwenden"
+
+#~ msgctxt "adaptive_layer_height_variation label"
+#~ msgid "Adaptive layers maximum variation"
+#~ msgstr "Maximale Abweichung für Anpassschichten"
+
+#~ msgctxt "adaptive_layer_height_variation_step label"
+#~ msgid "Adaptive layers variation step size"
+#~ msgstr "Abweichung Schrittgröße für Anpassschichten"
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive layers threshold"
+#~ msgstr "Schwellenwert Anpassschichten"
+
#~ msgctxt "skin_overlap description"
#~ msgid "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall."
#~ msgstr "Das Ausmaß des Überlappens zwischen der Außenhaut und den Wänden als Prozentwert der Außenhaut-Linienbreite. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Außenhaut herzustellen. Dies ist ein Prozentwert der durchschnittlichen Linienbreiten der Außenhautlinien und der innersten Wand."
diff --git a/resources/i18n/es_ES/cura.po b/resources/i18n/es_ES/cura.po
index aa217b0275..f971746925 100644
--- a/resources/i18n/es_ES/cura.po
+++ b/resources/i18n/es_ES/cura.po
@@ -5,20 +5,20 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
-"PO-Revision-Date: 2018-09-28 14:55+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Spanish\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: Spanish , Spanish \n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.2.3\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr "Ajustes de la máquina"
@@ -40,13 +40,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr "Archivo GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr "GCodeWriter no es compatible con el modo sin texto."
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr "Prepare el Gcode antes de la exportación."
@@ -56,7 +56,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "Asistente del modelo 3D"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,71 +70,50 @@ msgstr ""
"
Obtenga más información sobre cómo garantizar la mejor calidad y fiabilidad de impresión posible.
"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Changelog"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
-msgstr "Mostrar registro de cambios"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
msgctxt "@action"
msgid "Update Firmware"
msgstr "Actualizar firmware"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
-msgctxt "@item:inmenu"
-msgid "Flatten active settings"
-msgstr "Aplanar ajustes activos"
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "Archivo AMF"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:35
-msgctxt "@info:status"
-msgid "Profile has been flattened & activated."
-msgstr "El perfil se ha aplanado y activado."
-
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:33
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Impresión USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:34
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:43
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Imprimir mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:35
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:44
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Imprimir mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:71
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:80
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Conectado mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:96
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:105
msgctxt "@label"
msgid "A USB print is in progress, closing Cura will stop this print. Are you sure?"
msgstr "Se está realizando una impresión con USB, si cierra Cura detendrá la impresión. ¿Desea continuar?"
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/install/X3GWriter/__init__.py:15
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
-msgctxt "X3G Writer File Description"
-msgid "X3G File"
-msgstr "Archivo X3G"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "A print is still in progress. Cura cannot start another print via USB until the previous print has completed."
+msgstr "Todavía hay una impresión en curso. Cura no puede iniciar otra impresión a través de USB hasta que se haya completado la impresión anterior."
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
-msgctxt "X3g Writer Plugin Description"
-msgid "Writes X3g to files"
-msgstr "Escribe X3g en archivos"
-
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:21
-msgctxt "X3g Writer File Description"
-msgid "X3g File"
-msgstr "Archivo X3g"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "Print in Progress"
+msgstr "Impresión en curso"
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
@@ -148,6 +127,7 @@ msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeGzWriter no es compatible con el modo texto."
#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:28
+#: /home/ruben/Projects/Cura/plugins/UFPReader/__init__.py:22
msgctxt "@item:inlistbox"
msgid "Ultimaker Format Package"
msgstr "Paquete de formato Ultimaker"
@@ -169,7 +149,7 @@ msgid "Save to Removable Drive {0}"
msgstr "Guardar en unidad extraíble {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:107
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "¡No hay formatos de archivo disponibles con los que escribir!"
@@ -206,10 +186,9 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "No se pudo guardar en unidad extraíble {0}: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:152
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1629
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:139
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1668
msgctxt "@info:title"
msgid "Error"
msgstr "Error"
@@ -238,9 +217,9 @@ msgstr "Expulsar dispositivo extraíble {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:151
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:163
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1619
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1719
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1658
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1758
msgctxt "@info:title"
msgid "Warning"
msgstr "Advertencia"
@@ -267,337 +246,164 @@ msgctxt "@item:intext"
msgid "Removable Drive"
msgstr "Unidad extraíble"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:74
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py:26
+msgctxt "@action"
+msgid "Connect via Network"
+msgstr "Conectar a través de la red"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:57
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Imprimir a través de la red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:58
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Imprime a través de la red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
-msgctxt "@info:status"
-msgid "Connected over the network."
-msgstr "Conectado a través de la red."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
-msgctxt "@info:status"
-msgid "Connected over the network. Please approve the access request on the printer."
-msgstr "Conectado a través de la red. Apruebe la solicitud de acceso en la impresora."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:93
-msgctxt "@info:status"
-msgid "Connected over the network. No access to control the printer."
-msgstr "Conectado a través de la red. No hay acceso para controlar la impresora."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
-msgctxt "@info:status"
-msgid "Access to the printer requested. Please approve the request on the printer"
-msgstr "Acceso a la impresora solicitado. Apruebe la solicitud en la impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:101
-msgctxt "@info:title"
-msgid "Authentication status"
-msgstr "Estado de la autenticación"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
-msgctxt "@info:title"
-msgid "Authentication Status"
-msgstr "Estado de la autenticación"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:187
-msgctxt "@action:button"
-msgid "Retry"
-msgstr "Volver a intentar"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
-msgctxt "@info:tooltip"
-msgid "Re-send the access request"
-msgstr "Reenvía la solicitud de acceso"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
-msgctxt "@info:status"
-msgid "Access to the printer accepted"
-msgstr "Acceso a la impresora aceptado"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
-msgctxt "@info:status"
-msgid "No access to print with this printer. Unable to send print job."
-msgstr "No hay acceso para imprimir con esta impresora. No se puede enviar el trabajo de impresión."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:65
-msgctxt "@action:button"
-msgid "Request Access"
-msgstr "Solicitar acceso"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:66
-msgctxt "@info:tooltip"
-msgid "Send access request to the printer"
-msgstr "Envía la solicitud de acceso a la impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:201
-msgctxt "@label"
-msgid "Unable to start a new print job."
-msgstr "No se puede iniciar un nuevo trabajo de impresión."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:203
-msgctxt "@label"
-msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
-msgstr "Un problema con la configuración de Ultimaker impide iniciar la impresión. Soluciónelo antes de continuar."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:209
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:231
-msgctxt "@window:title"
-msgid "Mismatched configuration"
-msgstr "Configuración desajustada"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:223
-msgctxt "@label"
-msgid "Are you sure you wish to print with the selected configuration?"
-msgstr "¿Seguro que desea imprimir con la configuración seleccionada?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:225
-msgctxt "@label"
-msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "La configuración o calibración de la impresora y de Cura no coinciden. Para obtener el mejor resultado, segmente siempre los PrintCores y los materiales que se insertan en la impresora."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:252
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:162
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:162
-msgctxt "@info:status"
-msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
-msgstr "Envío de nuevos trabajos (temporalmente) bloqueado; se sigue enviando el trabajo de impresión previo."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:180
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
-msgctxt "@info:status"
-msgid "Sending data to printer"
-msgstr "Enviando datos a la impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:182
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:199
-msgctxt "@info:title"
-msgid "Sending Data"
-msgstr "Enviando datos"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:200
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:395
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:38
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:391
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:254
-msgctxt "@action:button"
-msgid "Cancel"
-msgstr "Cancelar"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:324
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr "No se ha cargado ningún PrintCore en la ranura {slot_number}."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:330
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No material loaded in slot {slot_number}"
-msgstr "No se ha cargado ningún material en la ranura {slot_number}."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:353
-#, python-brace-format
-msgctxt "@label"
-msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
-msgstr "PrintCore distinto (Cura: {cura_printcore_name}, impresora: {remote_printcore_name}) seleccionado para extrusor {extruder_id}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:362
-#, python-brace-format
-msgctxt "@label"
-msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr "Material distinto (Cura: {0}, impresora: {1}) seleccionado para extrusor {2}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:548
-msgctxt "@window:title"
-msgid "Sync with your printer"
-msgstr "Sincronizar con la impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:550
-msgctxt "@label"
-msgid "Would you like to use your current printer configuration in Cura?"
-msgstr "¿Desea utilizar la configuración actual de su impresora en Cura?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:552
-msgctxt "@label"
-msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Los PrintCores o los materiales de la impresora difieren de los del proyecto actual. Para obtener el mejor resultado, segmente siempre los PrintCores y materiales que se hayan insertado en la impresora."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:59
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Conectado a través de la red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:275
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:342
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:15
+msgctxt "@info:status"
+msgid "Please wait until the current job has been sent."
+msgstr "Espere hasta que se envíe el trabajo actual."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:16
+msgctxt "@info:title"
+msgid "Print error"
+msgstr "Error de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:21
+msgctxt "@info:title"
+msgid "New cloud printers found"
+msgstr "Se han encontrado nuevas impresoras en la nube"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:22
+msgctxt "@info:message"
+msgid "New printers have been found connected to your account, you can find them in your list of discovered printers."
+msgstr "Se han encontrado nuevas impresoras conectadas a tu cuenta; puedes verlas en la lista de impresoras descubiertas."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:27
+msgctxt "@info:option_text"
+msgid "Do not show this message again"
+msgstr "No volver a mostrar este mensaje"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:27
+#, python-brace-format
+msgctxt "@info:status"
+msgid "You are attempting to connect to {0} but it is not the host of a group. You can visit the web page to configure it as a group host."
+msgstr "Está intentando conectarse a {0} pero ese no es el host de un grupo. Puede visitar la página web para configurarlo como host de grupo."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:30
+msgctxt "@info:title"
+msgid "Not a group host"
+msgstr "No es un host de grupo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:35
+msgctxt "@action"
+msgid "Configure group"
+msgstr "Configurar grupo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:27
+msgctxt "@info:status"
+msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
+msgstr "Envíe y supervise sus trabajos de impresión desde cualquier lugar a través de su cuenta de Ultimaker."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:33
+msgctxt "@info:status Ultimaker Cloud should not be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Conectar a Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:36
+msgctxt "@action"
+msgid "Get started"
+msgstr "Empezar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Enviando trabajo de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading print job to printer."
+msgstr "Cargando el trabajo de impresión a la impresora."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:15
msgctxt "@info:status"
msgid "Print job was successfully sent to the printer."
msgstr "El trabajo de impresión se ha enviado correctamente a la impresora."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:277
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:343
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:16
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Fecha de envío"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:278
-msgctxt "@action:button"
-msgid "View in Monitor"
-msgstr "Ver en pantalla"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:390
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:290
-#, python-brace-format
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:18
msgctxt "@info:status"
-msgid "Printer '{printer_name}' has finished printing '{job_name}'."
-msgstr "{printer_name} ha terminado de imprimir «{job_name}»."
+msgid "You are attempting to connect to a printer that is not running Ultimaker Connect. Please update the printer to the latest firmware."
+msgstr "Está intentando conectarse a una impresora que no está ejecutando Ultimaker Connect. Actualice la impresora al firmware más reciente."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:392
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:294
-#, python-brace-format
-msgctxt "@info:status"
-msgid "The print job '{job_name}' was finished."
-msgstr "El trabajo de impresión '{job_name}' ha terminado."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:393
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:289
-msgctxt "@info:status"
-msgid "Print finished"
-msgstr "Impresión terminada"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:573
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:607
-msgctxt "@label:material"
-msgid "Empty"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:574
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:608
-msgctxt "@label:material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:151
-msgctxt "@action:button"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:152
-msgctxt "@properties:tooltip"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:153
-msgctxt "@info:status"
-msgid "Connected via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:163
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:21
msgctxt "@info:title"
-msgid "Cloud error"
-msgstr ""
+msgid "Update your printer"
+msgstr "Actualice su impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:180
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:24
+#, python-brace-format
msgctxt "@info:status"
-msgid "Could not export print job."
-msgstr ""
+msgid "Cura has detected material profiles that were not yet installed on the host printer of group {0}."
+msgstr "Cura ha detectado perfiles de material que aún no estaban instalados en la impresora host del grupo {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:330
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:26
+msgctxt "@info:title"
+msgid "Sending materials to printer"
+msgstr "Enviando materiales a la impresora"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:15
msgctxt "@info:text"
msgid "Could not upload the data to the printer."
-msgstr ""
+msgstr "No se han podido cargar los datos en la impresora."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:16
+msgctxt "@info:title"
+msgid "Network error"
+msgstr "Error de red"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:27
msgctxt "@info:status"
msgid "tomorrow"
-msgstr ""
+msgstr "mañana"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:30
msgctxt "@info:status"
msgid "today"
-msgstr ""
+msgstr "hoy"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:151
-msgctxt "@info:description"
-msgid "There was an error connecting to the cloud."
-msgstr ""
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:138
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Imprimir mediante Cloud"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:139
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Imprimir mediante Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:140
msgctxt "@info:status"
-msgid "Sending data to remote cluster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:456
-msgctxt "@info:status"
-msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:460
-msgctxt "@info:status"
-msgid "Connect to Ultimaker Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:461
-msgctxt "@action"
-msgid "Don't ask me again for this printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:464
-msgctxt "@action"
-msgid "Get started"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:478
-msgctxt "@info:status"
-msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:482
-msgctxt "@info:status"
-msgid "Connected!"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:486
-msgctxt "@action"
-msgid "Review your connection"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
-msgctxt "@action"
-msgid "Connect via Network"
-msgstr "Conectar a través de la red"
+msgid "Connected via Cloud"
+msgstr "Conectado mediante Cloud"
#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Supervisar"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:124
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:125
msgctxt "@info"
msgid "Could not access update information."
msgstr "No se pudo acceder a la información actualizada."
@@ -624,12 +430,12 @@ msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Vista de capas"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:117
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Cura no muestra correctamente las capas si la impresión de alambre está habilitada"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:118
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vista de simulación"
@@ -637,12 +443,12 @@ msgstr "Vista de simulación"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
msgctxt "@item:inmenu"
msgid "Post Processing"
-msgstr ""
+msgstr "Posprocesamiento"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
msgctxt "@item:inmenu"
msgid "Modify G-Code"
-msgstr ""
+msgstr "Modificar GCode"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12
msgctxt "@label"
@@ -654,46 +460,11 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr "Cree un volumen que no imprima los soportes."
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr "Cura recopila estadísticas de uso de forma anónima."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:55
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Recopilando datos"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:57
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Más información"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:58
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr "Obtenga más información sobre qué datos envía Cura."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:60
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Permitir"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:61
-msgctxt "@action:tooltip"
-msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
-msgstr "Permitir a Cura enviar estadísticas de uso de forma anónima para ayudar a priorizar mejoras futuras para Cura. Se envían algunas de sus preferencias y ajustes, la versión de Cura y un resumen de los modelos que está fragmentando."
-
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Perfiles de Cura 15.04"
-#: /home/ruben/Projects/Cura/plugins/R2D2/__init__.py:17
-msgctxt "@item:inmenu"
-msgid "Evaluation"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/ImageReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "JPG Image"
@@ -719,56 +490,86 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Imagen GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:15
+msgctxt "@item:inlistbox 'Open' is part of the name of this file format."
+msgid "Open Compressed Triangle Mesh"
+msgstr "Open Compressed Triangle Mesh"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:19
+msgctxt "@item:inlistbox"
+msgid "COLLADA Digital Asset Exchange"
+msgstr "COLLADA Digital Asset Exchange"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:23
+msgctxt "@item:inlistbox"
+msgid "glTF Binary"
+msgstr "glTF binario"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:27
+msgctxt "@item:inlistbox"
+msgid "glTF Embedded JSON"
+msgstr "glTF incrustado JSON"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:36
+msgctxt "@item:inlistbox"
+msgid "Stanford Triangle Format"
+msgstr "Stanford Triangle Format"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:40
+msgctxt "@item:inlistbox"
+msgid "Compressed COLLADA Digital Asset Exchange"
+msgstr "COLLADA Digital Asset Exchange comprimido"
+
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
msgctxt "@info:status"
msgid "Unable to slice with the current material as it is incompatible with the selected machine or configuration."
msgstr "No se puede segmentar con el material actual, ya que es incompatible con el dispositivo o la configuración seleccionados."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:389
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:398
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:407
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:416
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:362
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:386
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:395
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:404
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:413
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "No se puede segmentar"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "Los ajustes actuales no permiten la segmentación. Los siguientes ajustes contienen errores: {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}"
msgstr "Los ajustes de algunos modelos no permiten la segmentación. Los siguientes ajustes contienen errores en uno o más modelos: {error_labels}."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:394
msgctxt "@info:status"
msgid "Unable to slice because the prime tower or prime position(s) are invalid."
msgstr "No se puede segmentar porque la torre auxiliar o la posición o posiciones de preparación no son válidas."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid "Unable to slice because there are objects associated with disabled Extruder %s."
msgstr "No se puede segmentar porque hay objetos asociados al extrusor %s que está deshabilitado."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:412
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume or are assigned to a disabled extruder. Please scale or rotate models to fit, or enable an extruder."
-msgstr ""
+msgstr "No hay nada que segmentar porque ninguno de los modelos se adapta al volumen de impresión o los modelos están asignados a un extrusor deshabilitado. Escale o rote los modelos para que se adapten o habilite un extrusor."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Procesando capas"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Información"
@@ -783,12 +584,12 @@ msgctxt "@info:tooltip"
msgid "Configure Per Model Settings"
msgstr "Configurar ajustes por modelo"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:186
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Recomendado"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:188
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personalizado"
@@ -799,19 +600,19 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "Archivo 3MF"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:190
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:763
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:198
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:651
msgctxt "@label"
msgid "Nozzle"
msgstr "Tobera"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:469
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:496
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Project file {0} contains an unknown machine type {1}. Cannot import the machine. Models will be imported instead."
-msgstr "El archivo del proyecto{0} contiene un tipo de máquina desconocida {1}. No se puede importar la máquina, en su lugar, se importarán los modelos."
+msgstr "El archivo del proyecto {0} contiene un tipo de máquina desconocida {1}. No se puede importar la máquina, en su lugar, se importarán los modelos."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:472
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:499
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Abrir archivo de proyecto"
@@ -826,18 +627,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Archivo G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:324
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:335
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Analizar GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:326
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:476
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:337
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:491
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Datos de GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:474
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:489
msgctxt "@info:generic"
msgid "Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."
msgstr "Asegúrese de que el GCode es adecuado para la impresora y para su configuración antes de enviar el archivo a la misma. Es posible que la representación del GCode no sea precisa."
@@ -845,7 +646,7 @@ msgstr "Asegúrese de que el GCode es adecuado para la impresora y para su confi
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
msgctxt "@item:inmenu"
msgid "Manage backups"
-msgstr ""
+msgstr "Administrar copias de seguridad"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
@@ -858,32 +659,32 @@ msgstr "Copia de seguridad"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
msgctxt "@info:backup_status"
msgid "There was an error listing your backups."
-msgstr ""
+msgstr "Se ha producido un error al obtener sus copias de seguridad."
-#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:121
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:132
msgctxt "@info:backup_status"
msgid "There was an error trying to restore your backup."
-msgstr ""
+msgstr "Se ha producido un error al intentar restaurar su copia de seguridad."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:15
msgctxt "@info:title"
msgid "Backups"
-msgstr ""
+msgstr "Copias de seguridad"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
msgctxt "@info:backup_status"
msgid "Uploading your backup..."
-msgstr ""
+msgstr "Cargando su copia de seguridad..."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:36
msgctxt "@info:backup_status"
msgid "There was an error while uploading your backup."
-msgstr ""
+msgstr "Se ha producido un error al cargar su copia de seguridad."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:39
msgctxt "@info:backup_status"
msgid "Your backup has finished uploading."
-msgstr ""
+msgstr "Su copia de seguridad ha terminado de cargarse."
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
@@ -891,16 +692,6 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Perfil de cura"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
-msgctxt "@item:inmenu"
-msgid "Profile Assistant"
-msgstr "Asistente del perfil"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
-msgctxt "@item:inlistbox"
-msgid "Profile Assistant"
-msgstr "Asistente del perfil"
-
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:26
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -919,274 +710,365 @@ msgstr "Error al escribir el archivo 3MF."
#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
msgctxt "@item:inmenu"
msgid "Preview"
-msgstr ""
+msgstr "Vista previa"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Seleccionar actualizaciones"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
-msgctxt "@action"
-msgid "Checkup"
-msgstr "Comprobación"
-
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
msgstr "Nivelar placa de impresión"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:81
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Pared exterior"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:82
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Paredes interiores"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:83
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Forro"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:84
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Relleno"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:85
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Relleno de soporte"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:86
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Interfaz de soporte"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:87
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Soporte"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:88
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Falda"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Desplazamiento"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Retracciones"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Otro"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:309
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Archivo {0} presegmentado"
-
-#: /home/ruben/Projects/Cura/cura/API/Account.py:77
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
msgctxt "@info:title"
msgid "Login failed"
msgstr "Fallo de inicio de sesión"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:201
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:36
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "No compatible"
+
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:55
+msgctxt "@info:No intent profile selected"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:196
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:125
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "El archivo ya existe"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:202
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:197
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:126
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "El archivo {0} ya existe. ¿Está seguro de que desea sobrescribirlo?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:425
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:428
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:433
msgctxt "@info:status"
msgid "Invalid file URL:"
-msgstr ""
+msgstr "URL del archivo no válida:"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:206
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "No reemplazado"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:780
+msgctxt "@info:message Followed by a list of settings."
+msgid "Settings have been changed to match the current availability of extruders:"
+msgstr "La configuración se ha cambiado para que coincida con los extrusores disponibles en este momento:"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:915
-#, python-format
-msgctxt "@info:generic"
-msgid "Settings have been changed to match the current availability of extruders: [%s]"
-msgstr "La configuración se ha cambiado para que coincida con los extrusores disponibles en este momento: [%s]."
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:917
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:782
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Ajustes actualizados"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1458
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1334
msgctxt "@info:title"
msgid "Extruder(s) Disabled"
-msgstr ""
+msgstr "Extrusores deshabilitados"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1457
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:99
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:86
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:182
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:223
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:137
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "Error al exportar el perfil a {0}: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:138
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "Error al exportar el perfil a {0}: Error en el complemento de escritura."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:149
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "Perfil exportado a {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:150
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Exportación correcta"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr ""
-
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
-msgid "Can't import profile from {0} before a printer is added."
-msgstr ""
+msgid "Failed to import profile from {0}: {1}"
+msgstr "Error al importar el perfil de {0}: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:181
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags !"
+msgid "Can't import profile from {0} before a printer is added."
+msgstr "No se puede importar el perfil de {0} antes de añadir una impresora."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:198
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "No custom profile to import in file {0}"
-msgstr "No hay ningún perfil personalizado para importar en el archivo {0}."
+msgstr "No hay ningún perfil personalizado para importar en el archivo {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:202
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}:"
msgstr "Error al importar el perfil de {0}:"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:226
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:236
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "This profile {0} contains incorrect data, could not import it."
msgstr "Este perfil {0} contiene datos incorrectos, no se han podido importar."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:241
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:325
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
-msgstr "El equipo definido en el perfil {0} ({1}) no coincide con el equipo actual ({2}), no se ha podido importar."
-
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to import profile from {0}:"
msgstr "Error al importar el perfil de {0}:"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:328
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Perfil {0} importado correctamente"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:319
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:331
#, python-brace-format
msgctxt "@info:status"
msgid "File {0} does not contain any valid profile."
msgstr "El archivo {0} no contiene ningún perfil válido."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:322
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:334
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "El perfil {0} tiene un tipo de archivo desconocido o está corrupto."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:340
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:369
msgctxt "@label"
msgid "Custom profile"
msgstr "Perfil personalizado"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:385
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "Al perfil le falta un tipo de calidad."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:370
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:399
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "No se ha podido encontrar un tipo de calidad {0} para la configuración actual."
-#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:69
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:76
+msgctxt "@tooltip"
+msgid "Outer Wall"
+msgstr "Pared exterior"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:77
+msgctxt "@tooltip"
+msgid "Inner Walls"
+msgstr "Paredes interiores"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:78
+msgctxt "@tooltip"
+msgid "Skin"
+msgstr "Forro"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:79
+msgctxt "@tooltip"
+msgid "Infill"
+msgstr "Relleno"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:80
+msgctxt "@tooltip"
+msgid "Support Infill"
+msgstr "Relleno de soporte"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:81
+msgctxt "@tooltip"
+msgid "Support Interface"
+msgstr "Interfaz de soporte"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:82
+msgctxt "@tooltip"
+msgid "Support"
+msgstr "Soporte"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:83
+msgctxt "@tooltip"
+msgid "Skirt"
+msgstr "Falda"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:84
+msgctxt "@tooltip"
+msgid "Prime Tower"
+msgstr "Torre auxiliar"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:85
+msgctxt "@tooltip"
+msgid "Travel"
+msgstr "Desplazamiento"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:86
+msgctxt "@tooltip"
+msgid "Retractions"
+msgstr "Retracciones"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:87
+msgctxt "@tooltip"
+msgid "Other"
+msgstr "Otro"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:302
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "Archivo {0} presegmentado"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Siguiente"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:62
#, python-brace-format
msgctxt "@label"
msgid "Group #{group_nr}"
msgstr "N.º de grupo {group_nr}"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:65
-msgctxt "@info:title"
-msgid "Network enabled printers"
-msgstr "Impresoras de red habilitadas"
+#: /home/ruben/Projects/Cura/cura/UI/WhatsNewPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:169
+msgctxt "@action:button"
+msgid "Close"
+msgstr "Cerrar"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:80
-msgctxt "@info:title"
-msgid "Local printers"
-msgstr "Impresoras locales"
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Agregar"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:18
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:352
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:58
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:149
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:406
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:294
+msgctxt "@action:button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:36
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:320
+msgctxt "@label"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:39
+msgctxt "@label"
+msgid "Visual"
+msgstr "Visual"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:40
+msgctxt "@text"
+msgid "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality."
+msgstr "El perfil visual está diseñado para imprimir prototipos y modelos visuales con la intención de obtener una alta calidad visual y de superficies."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:43
+msgctxt "@label"
+msgid "Engineering"
+msgstr "Engineering"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:44
+msgctxt "@text"
+msgid "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances."
+msgstr "El perfil de ingeniería ha sido diseñado para imprimir prototipos funcionales y piezas de uso final con la intención de obtener una mayor precisión y tolerancias"
+" más precisas."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:47
+msgctxt "@label"
+msgid "Draft"
+msgstr "Boceto"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:48
+msgctxt "@text"
+msgid "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction."
+msgstr "El perfil del boceto ha sido diseñado para imprimir los prototipos iniciales y la validación del concepto con la intención de reducir el tiempo de impresión"
+" de manera considerable."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr "No reemplazado"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:357
+msgctxt "@label"
+msgid "Custom profiles"
+msgstr "Perfiles personalizados"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:391
#, python-brace-format
msgctxt "@item:inlistbox"
msgid "All Supported Types ({0})"
msgstr "Todos los tipos compatibles ({0})"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:110
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:392
msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Todos los archivos (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:665
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:213
msgctxt "@label"
msgid "Custom Material"
msgstr "Material personalizado"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:666
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:256
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:214
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:205
msgctxt "@label"
msgid "Custom"
msgstr "Personalizado"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:116
+msgctxt "@label"
+msgid "The printer(s) below cannot be connected because they are part of a group"
+msgstr "Las siguientes impresoras no pueden conectarse porque forman parte de un grupo"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:118
+msgctxt "@label"
+msgid "Available networked printers"
+msgstr "Impresoras en red disponibles"
+
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:90
msgctxt "@info:status"
msgid "The build volume height has been reduced due to the value of the \"Print Sequence\" setting to prevent the gantry from colliding with printed models."
msgstr "La altura del volumen de impresión se ha reducido debido al valor del ajuste «Secuencia de impresión» para evitar que el caballete colisione con los modelos impresos."
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:83
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:92
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volumen de impresión"
@@ -1201,52 +1083,67 @@ msgctxt "@info:backup_failed"
msgid "Tried to restore a Cura backup without having proper data or meta data."
msgstr "Se ha intentado restaurar una copia de seguridad de Cura sin tener los datos o metadatos adecuados."
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:124
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:125
msgctxt "@info:backup_failed"
-msgid "Tried to restore a Cura backup that does not match your current version."
-msgstr "Se ha intentado restaurar una copia de seguridad de Cura que no coincide con la versión actual."
+msgid "Tried to restore a Cura backup that is higher than the current version."
+msgstr "Se ha intentado restaurar una copia de seguridad de Cura superior a la versión actual."
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr "No se ha podido leer la respuesta."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
msgctxt "@info"
msgid "Unable to reach the Ultimaker account server."
-msgstr ""
+msgstr "No se puede acceder al servidor de cuentas de Ultimaker."
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:70
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr "Conceda los permisos necesarios al autorizar esta aplicación."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:77
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
+msgstr "Se ha producido un problema al intentar iniciar sesión, vuelva a intentarlo."
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:29
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Multiplicar y colocar objetos"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:30
msgctxt "@info:title"
msgid "Placing Objects"
-msgstr ""
+msgstr "Colocando objetos"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:149
msgctxt "@info:status"
msgid "Unable to find a location within the build volume for all objects"
msgstr "No se puede encontrar una ubicación dentro del volumen de impresión para todos los objetos"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Colocando objeto"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:30
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:67
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:66
msgctxt "@info:status"
msgid "Finding new location for objects"
msgstr "Buscando nueva ubicación para los objetos"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:34
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:71
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:70
msgctxt "@info:title"
msgid "Finding Location"
msgstr "Buscando ubicación"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "No se puede encontrar la ubicación"
@@ -1377,242 +1274,205 @@ msgstr "Registros"
#: /home/ruben/Projects/Cura/cura/CrashHandler.py:322
msgctxt "@title:groupbox"
-msgid "User description"
-msgstr "Descripción del usuario"
+msgid "User description (Note: Developers may not speak your language, please use English if possible)"
+msgstr "Descripción del usuario (Nota: es posible que los desarrolladores no hablen su idioma; si es posible, utilice el inglés)"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:341
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Enviar informe"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:480
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:513
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Cargando máquinas..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:781
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:520
+msgctxt "@info:progress"
+msgid "Setting up preferences..."
+msgstr "Configurando preferencias...."
+
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:824
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Configurando escena..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:817
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:859
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Cargando interfaz..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1059
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1150
#, python-format
msgctxt "@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm."
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr "%(width).1f x %(depth).1f x %(height).1f mm"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1618
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1657
#, python-brace-format
msgctxt "@info:status"
msgid "Only one G-code file can be loaded at a time. Skipped importing {0}"
msgstr "Solo se puede cargar un archivo GCode a la vez. Se omitió la importación de {0}"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1628
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1667
#, python-brace-format
msgctxt "@info:status"
msgid "Can't open any other file if G-code is loading. Skipped importing {0}"
msgstr "No se puede abrir ningún archivo si se está cargando un archivo GCode. Se omitió la importación de {0}"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1718
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1757
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "No se puede cargar el modelo seleccionado, es demasiado pequeño."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:62
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Ajustes de la máquina"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:81
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Impresora"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:100
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:56
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Ajustes de la impresora"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:70
msgctxt "@label"
msgid "X (Width)"
msgstr "X (anchura)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:112
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:122
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:132
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:387
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:429
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:441
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:897
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:74
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:88
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:102
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:243
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:265
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:285
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:79
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:93
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:109
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:124
msgctxt "@label"
msgid "mm"
msgstr "mm"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:84
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (profundidad)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:98
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (altura)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:143
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:112
msgctxt "@label"
msgid "Build plate shape"
msgstr "Forma de la placa de impresión"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:152
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:125
+msgctxt "@label"
msgid "Origin at center"
msgstr "Origen en el centro"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:160
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:137
+msgctxt "@label"
msgid "Heated bed"
-msgstr "Plataforma caliente"
+msgstr "Plataforma calentada"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:171
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:149
+msgctxt "@label"
+msgid "Heated build volume"
+msgstr "Volumen de impresión calentado"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:161
msgctxt "@label"
msgid "G-code flavor"
msgstr "Tipo de GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:184
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:185
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Ajustes del cabezal de impresión"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:199
msgctxt "@label"
msgid "X min"
msgstr "X mín."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:195
-msgctxt "@tooltip"
-msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distancia desde la parte izquierda del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:219
msgctxt "@label"
msgid "Y min"
msgstr "Y mín."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:205
-msgctxt "@tooltip"
-msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distancia desde la parte frontal del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:239
msgctxt "@label"
msgid "X max"
msgstr "X máx."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:215
-msgctxt "@tooltip"
-msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distancia desde la parte derecha del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:261
msgctxt "@label"
msgid "Y max"
msgstr "Y máx."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:225
-msgctxt "@tooltip"
-msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distancia desde la parte trasera del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:281
msgctxt "@label"
-msgid "Gantry height"
-msgstr "Altura del caballete"
+msgid "Gantry Height"
+msgstr "Altura del puente"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:239
-msgctxt "@tooltip"
-msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
-msgstr "Diferencia de altura entre la punta de la tobera y el sistema del puente (ejes X e Y). Se usa para evitar que colisionen la impresión anterior con el caballete al imprimir «de uno en uno»."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:258
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:295
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Número de extrusores"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:314
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "Start G-code"
msgstr "Iniciar GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:324
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr "Los comandos de GCode que se ejecutarán justo al inicio."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:333
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:366
+msgctxt "@title:label"
msgid "End G-code"
msgstr "Finalizar GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:343
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very end."
-msgstr "Los comandos de GCode que se ejecutarán justo al final."
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:42
+msgctxt "@title:tab"
+msgid "Printer"
+msgstr "Impresora"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:374
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:63
+msgctxt "@title:label"
msgid "Nozzle Settings"
msgstr "Ajustes de la tobera"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr "Tamaño de la tobera"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr "Diámetro del material compatible"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:404
-msgctxt "@tooltip"
-msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
-msgstr "El diámetro nominal del filamento compatible con la impresora. El diámetro exacto se sobrescribirá según el material o el perfil."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:428
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Desplazamiento de la tobera sobre el eje X"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:440
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:120
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Desplazamiento de la tobera sobre el eje Y"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:452
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:135
msgctxt "@label"
msgid "Cooling Fan Number"
msgstr "Número de ventilador de enfriamiento"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:453
-msgctxt "@label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:473
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "GCode inicial del extrusor"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:491
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "GCode final del extrusor"
@@ -1622,7 +1482,7 @@ msgid "Install"
msgstr "Instalar"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Instalado"
@@ -1635,18 +1495,18 @@ msgstr "No se ha podido conectar con la base de datos del Paquete Cura. Comprueb
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
msgctxt "@label"
msgid "ratings"
-msgstr ""
+msgstr "calificaciones"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:28
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:32
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:30
msgctxt "@title:tab"
msgid "Plugins"
msgstr "Complementos"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:69
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:42
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:361
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:77
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiales"
@@ -1654,54 +1514,51 @@ msgstr "Materiales"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
msgctxt "@label"
msgid "Your rating"
-msgstr ""
+msgstr "Su calificación"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:98
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:99
msgctxt "@label"
msgid "Version"
msgstr "Versión"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:105
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:106
msgctxt "@label"
msgid "Last updated"
msgstr "Última actualización"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:112
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:260
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:113
msgctxt "@label"
msgid "Author"
msgstr "Autor"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:119
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:120
msgctxt "@label"
msgid "Downloads"
msgstr "Descargas"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:181
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:222
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:265
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Desconocido"
-
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:56
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to install or update"
-msgstr ""
+msgstr "Inicie sesión para realizar la instalación o la actualización"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:73
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:80
+msgctxt "@label:The string between and is the highlighted link"
+msgid "Buy material spools"
+msgstr "Comprar bobinas de material"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:96
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:34
msgctxt "@action:button"
msgid "Update"
msgstr "Actualizar"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:74
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:97
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:35
msgctxt "@action:button"
msgid "Updating"
msgstr "Actualizando"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:75
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:98
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:36
msgctxt "@action:button"
msgid "Updated"
@@ -1710,7 +1567,7 @@ msgstr "Actualizado"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
msgid "Marketplace"
-msgstr ""
+msgstr "Marketplace"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1745,12 +1602,12 @@ msgstr "Confirmar"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to login first before you can rate"
-msgstr ""
+msgstr "Debe iniciar sesión antes de enviar sus calificaciones"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to install the package before you can rate"
-msgstr ""
+msgstr "Debe instalar el paquete antes de enviar sus calificaciones"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
@@ -1762,22 +1619,22 @@ msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Salir de Cura"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Contributions"
msgstr "Contribuciones de la comunidad"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Plugins"
msgstr "Complementos de la comunidad"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:43
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:40
msgctxt "@label"
msgid "Generic Materials"
msgstr "Materiales genéricos"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:56
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Instalado"
@@ -1790,7 +1647,7 @@ msgstr "Se instalará después de reiniciar"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:53
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to update"
-msgstr ""
+msgstr "Inicie sesión para realizar la actualización"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
@@ -1833,42 +1690,62 @@ msgctxt "@label"
msgid "Featured"
msgstr "Destacado"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:34
msgctxt "@label"
msgid "Compatibility"
msgstr "Compatibilidad"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:124
+msgctxt "@label:table_header"
+msgid "Machine"
+msgstr "Máquina"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:137
+msgctxt "@label:table_header"
+msgid "Build Plate"
+msgstr "Placa de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:143
+msgctxt "@label:table_header"
+msgid "Support"
+msgstr "Soporte"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:149
+msgctxt "@label:table_header"
+msgid "Quality"
+msgstr "Calidad"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:170
msgctxt "@action:label"
msgid "Technical Data Sheet"
-msgstr ""
+msgstr "Especificaciones técnicas"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:179
msgctxt "@action:label"
msgid "Safety Data Sheet"
-msgstr ""
+msgstr "Especificaciones de seguridad"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:188
msgctxt "@action:label"
msgid "Printing Guidelines"
-msgstr ""
+msgstr "Directrices de impresión"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:197
msgctxt "@action:label"
msgid "Website"
-msgstr ""
+msgstr "Sitio web"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml:16
msgctxt "@info"
msgid "Fetching packages..."
msgstr "Buscando paquetes..."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:90
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:91
msgctxt "@label"
msgid "Website"
msgstr "Sitio web"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:97
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "Correo electrónico"
@@ -1876,23 +1753,7 @@ msgstr "Correo electrónico"
#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.qml:22
msgctxt "@info:tooltip"
msgid "Some things could be problematic in this print. Click to see tips for adjustment."
-msgstr "Algunos elementos pueden causar problemas durante la impresión. Haga clic para ver consejos sobre cómo ajustarla."
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
-msgctxt "@label"
-msgid "Changelog"
-msgstr "Registro de cambios"
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:85
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
-msgctxt "@action:button"
-msgid "Close"
-msgstr "Cerrar"
+msgstr "Algunos elementos pueden causar problemas durante la impresión. Haga clic para ver consejos sobre cómo ajustarlos."
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
msgctxt "@title"
@@ -1969,77 +1830,79 @@ msgctxt "@label"
msgid "Firmware update failed due to missing firmware."
msgstr "Se ha producido un error al actualizar el firmware porque falta el firmware."
-#: /home/ruben/Projects/Cura/plugins/UserAgreement/UserAgreement.qml:16
-msgctxt "@title:window"
-msgid "User Agreement"
-msgstr "Acuerdo de usuario"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:155
+msgctxt "@label link to Connect and Cloud interfaces"
+msgid "Manage printer"
+msgstr "Administrar impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:254
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:192
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:183
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
+msgstr "Vidrio"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:256
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:514
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:248
msgctxt "@info"
-msgid "These options are not available because you are monitoring a cloud printer."
-msgstr ""
+msgid "Please update your printer's firmware to manage the queue remotely."
+msgstr "Actualice el firmware de la impresora para gestionar la cola de forma remota."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:289
msgctxt "@info"
msgid "The webcam is not available because you are monitoring a cloud printer."
-msgstr ""
+msgstr "La cámara web no se encuentra disponible porque está supervisando una impresora en la nube."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:301
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:348
msgctxt "@label:status"
msgid "Loading..."
-msgstr ""
+msgstr "Cargando..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:305
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:352
msgctxt "@label:status"
msgid "Unavailable"
msgstr "No disponible"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:309
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:356
msgctxt "@label:status"
msgid "Unreachable"
-msgstr ""
+msgstr "No se puede conectar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:360
msgctxt "@label:status"
msgid "Idle"
-msgstr ""
+msgstr "Sin actividad"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
msgctxt "@label"
msgid "Untitled"
-msgstr ""
+msgstr "Sin título"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:373
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:422
msgctxt "@label"
msgid "Anonymous"
-msgstr ""
+msgstr "Anónimo"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:399
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:449
msgctxt "@label:status"
msgid "Requires configuration changes"
-msgstr ""
+msgstr "Debe cambiar la configuración"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:436
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:487
msgctxt "@action:button"
msgid "Details"
-msgstr ""
+msgstr "Detalles"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
msgctxt "@label"
msgid "Unavailable printer"
-msgstr ""
+msgstr "Impresora no disponible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:134
msgctxt "@label"
msgid "First available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:187
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:132
-msgctxt "@label"
-msgid "Glass"
-msgstr "Vidrio"
+msgstr "Primera disponible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
msgctxt "@label"
@@ -2048,196 +1911,193 @@ msgstr "En cola"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
msgctxt "@label link to connect manager"
-msgid "Go to Cura Connect"
-msgstr ""
+msgid "Manage in browser"
+msgstr "Gestionar en el navegador"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:100
+msgctxt "@label"
+msgid "There are no print jobs in the queue. Slice and send a job to add one."
+msgstr "No hay trabajos de impresión en la cola. Segmentar y enviar un trabajo para añadir uno."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:115
msgctxt "@label"
msgid "Print jobs"
-msgstr ""
+msgstr "Trabajos de impresión"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:131
msgctxt "@label"
msgid "Total print time"
-msgstr ""
+msgstr "Tiempo de impresión total"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:130
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:147
msgctxt "@label"
msgid "Waiting for"
-msgstr ""
+msgstr "Esperando"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:246
-msgctxt "@label link to connect manager"
-msgid "View print history"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:46
-msgctxt "@window:title"
-msgid "Existing Connection"
-msgstr "Conexión existente"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:48
-msgctxt "@message:text"
-msgid "This printer/group is already added to Cura. Please select another printer/group."
-msgstr "Esta impresora o grupo de impresoras ya se ha añadido a Cura. Seleccione otra impresora o grupo de impresoras."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:65
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Conectar con la impresora en red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
msgctxt "@label"
-msgid ""
-"To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
-"\n"
-"Select your printer from the list below:"
-msgstr ""
-"Para imprimir directamente en la impresora a través de la red, asegúrese de que esta está conectada a la red utilizando un cable de red o conéctela a la red wifi. Si no conecta Cura con la impresora, también puede utilizar una unidad USB para transferir archivos GCode a la impresora.\n"
-"\n"
-"Seleccione la impresora de la siguiente lista:"
+msgid "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer."
+msgstr "Para imprimir directamente a través de la red, asegúrese de que la impresora está conectada a la red mediante un cable de red o conéctela a la red wifi. Si no conecta Cura con la impresora, también puede utilizar una unidad USB para transferir archivos GCode a la impresora."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Agregar"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
+msgctxt "@label"
+msgid "Select your printer from the list below:"
+msgstr "Seleccione la impresora en la lista siguiente:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:97
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
msgctxt "@action:button"
msgid "Edit"
msgstr "Editar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:108
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:138
msgctxt "@action:button"
msgid "Remove"
msgstr "Eliminar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:96
msgctxt "@action:button"
msgid "Refresh"
msgstr "Actualizar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:211
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:176
msgctxt "@label"
msgid "If your printer is not listed, read the network printing troubleshooting guide"
msgstr "Si la impresora no aparece en la lista, lea la guía de solución de problemas de impresión y red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:240
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:258
msgctxt "@label"
msgid "Type"
msgstr "Tipo"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:279
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:274
msgctxt "@label"
msgid "Firmware version"
msgstr "Versión de firmware"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:290
msgctxt "@label"
msgid "Address"
msgstr "Dirección"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:317
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:263
msgctxt "@label"
msgid "This printer is not set up to host a group of printers."
msgstr "Esta impresora no está configurada para alojar un grupo de impresoras."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:267
msgctxt "@label"
msgid "This printer is the host for a group of %1 printers."
msgstr "Esta impresora aloja un grupo de %1 impresoras."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:332
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:278
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr "La impresora todavía no ha respondido en esta dirección."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:337
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
msgctxt "@action:button"
msgid "Connect"
msgstr "Conectar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:351
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:296
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Dirección IP no válida"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:146
+msgctxt "@text"
+msgid "Please enter a valid IP address."
+msgstr "Introduzca una dirección IP válida."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:308
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Dirección de la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:374
-msgctxt "@alabel"
-msgid "Enter the IP address or hostname of your printer on the network."
-msgstr "Introduzca la dirección IP o el nombre de host de la impresora en red."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
+msgid "Enter the IP address of your printer on the network."
+msgstr "Introduzca la dirección IP de la impresora en la red."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:404
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:361
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:138
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
msgstr "Aceptar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
msgctxt "@label:status"
msgid "Aborted"
msgstr "Cancelado"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:80
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:82
msgctxt "@label:status"
msgid "Finished"
msgstr "Terminado"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:86
msgctxt "@label:status"
msgid "Preparing..."
-msgstr ""
+msgstr "Preparando..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
msgctxt "@label:status"
msgid "Aborting..."
-msgstr ""
+msgstr "Cancelando..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
msgctxt "@label:status"
msgid "Pausing..."
-msgstr ""
+msgstr "Pausando..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:104
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
msgctxt "@label:status"
msgid "Paused"
msgstr "En pausa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
msgctxt "@label:status"
msgid "Resuming..."
-msgstr ""
+msgstr "Reanudando..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:108
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
msgctxt "@label:status"
msgid "Action required"
msgstr "Acción requerida"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:110
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
msgctxt "@label:status"
msgid "Finishes %1 at %2"
-msgstr ""
+msgstr "Termina el %1 a las %2"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:44
-msgctxt "@action:button"
-msgid "Print"
-msgstr "Imprimir"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:11
msgctxt "@title:window"
msgid "Print over network"
msgstr "Imprimir a través de la red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:52
+msgctxt "@action:button"
+msgid "Print"
+msgstr "Imprimir"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:80
msgctxt "@label"
msgid "Printer selection"
msgstr "Selección de la impresora"
@@ -2261,12 +2121,12 @@ msgstr "Reanudar"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
msgctxt "@label"
msgid "Pausing..."
-msgstr ""
+msgstr "Pausando..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
msgctxt "@label"
msgid "Resuming..."
-msgstr ""
+msgstr "Reanudando..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
@@ -2278,7 +2138,7 @@ msgstr "Pausar"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Aborting..."
-msgstr ""
+msgstr "Cancelando..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
@@ -2319,161 +2179,156 @@ msgstr "Cancela la impresión"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
msgctxt "@title:window"
msgid "Configuration Changes"
-msgstr ""
+msgstr "Cambios de configuración"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
msgctxt "@action:button"
msgid "Override"
-msgstr ""
+msgstr "Anular"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:64
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:85
msgctxt "@label"
msgid "The assigned printer, %1, requires the following configuration change:"
msgid_plural "The assigned printer, %1, requires the following configuration changes:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Es necesario realizar el siguiente cambio de configuración en la impresora asignada %1:"
+msgstr[1] "Es necesario realizar los siguientes cambios de configuración en la impresora asignada %1:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:68
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:89
msgctxt "@label"
msgid "The printer %1 is assigned, but the job contains an unknown material configuration."
-msgstr "Se ha asignado la impresora 1%, pero el trabajo tiene una configuración de material desconocido."
+msgstr "Se ha asignado la impresora %1, pero el trabajo tiene una configuración de material desconocido."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:99
msgctxt "@label"
msgid "Change material %1 from %2 to %3."
msgstr "Cambiar material %1, de %2 a %3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:102
msgctxt "@label"
msgid "Load %3 as material %1 (This cannot be overridden)."
msgstr "Cargar %3 como material %1 (no se puede anular)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:105
msgctxt "@label"
msgid "Change print core %1 from %2 to %3."
msgstr "Cambiar print core %1, de %2 a %3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:108
msgctxt "@label"
msgid "Change build plate to %1 (This cannot be overridden)."
msgstr "Cambiar la placa de impresión a %1 (no se puede anular)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:94
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:115
msgctxt "@label"
msgid "Override will use the specified settings with the existing printer configuration. This may result in a failed print."
-msgstr ""
+msgstr "Al sobrescribir la configuración se usarán los ajustes especificados con la configuración de impresora existente. Esto podría provocar un fallo en la impresión."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:135
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:156
msgctxt "@label"
msgid "Aluminum"
msgstr "Aluminio"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:75
-msgctxt "@info:tooltip"
-msgid "Connect to a printer"
-msgstr "Conecta a una impresora"
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:92
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:100
msgctxt "@info"
msgid ""
"Please make sure your printer has a connection:\n"
"- Check if the printer is turned on.\n"
-"- Check if the printer is connected to the network."
+"- Check if the printer is connected to the network.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
+"Asegúrese de que la impresora está conectada:\n"
+"- Compruebe que la impresora está encendida.\n"
+"- Compruebe que la impresora está conectada a la red.\n"
+"- Compruebe que ha iniciado sesión para ver impresoras conectadas a la nube."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:110
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
msgctxt "@info"
-msgid "Please select a network connected printer to monitor."
-msgstr ""
+msgid "Please connect your printer to the network."
+msgstr "Conecte su impresora a la red."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:126
-msgctxt "@info"
-msgid "Please connect your Ultimaker printer to your local network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:165
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
msgctxt "@label link to technical assistance"
msgid "View user manuals online"
-msgstr ""
+msgstr "Ver manuales de usuario en línea"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:18
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:47
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr "Combinación de colores"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:105
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Color del material"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:109
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Tipo de línea"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:113
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Velocidad"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:117
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Grosor de la capa"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:154
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Modo de compatibilidad"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:229
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
msgid "Travels"
-msgstr ""
+msgstr "Desplazamientos"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:235
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
msgid "Helpers"
-msgstr ""
+msgstr "Asistentes"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:241
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
msgid "Shell"
-msgstr ""
+msgstr "Perímetro"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:247
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
msgid "Infill"
msgstr "Relleno"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Mostrar solo capas superiores"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:307
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:308
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr "Mostrar cinco capas detalladas en la parte superior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Superior o inferior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:325
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Pared interior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "mín."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:432
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "máx."
@@ -2503,30 +2358,25 @@ msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Cambia las secuencias de comandos de posprocesamiento"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:16
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:17
msgctxt "@title:window"
msgid "More information on anonymous data collection"
msgstr "Más información sobre la recopilación de datos anónimos"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:66
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:74
msgctxt "@text:window"
-msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
-msgstr "Cura envía datos anónimos a Ultimaker para mejorar la calidad de impresión y la experiencia de usuario. A continuación, hay un ejemplo de todos los datos que se han enviado."
+msgid "Ultimaker Cura collects anonymous data in order to improve the print quality and user experience. Below is an example of all the data that is shared:"
+msgstr "Ultimaker Cura recopila datos anónimos para mejorar la calidad de impresión y la experiencia de usuario. A continuación, hay un ejemplo de todos los datos que se comparten:"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:101
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:109
msgctxt "@text:window"
-msgid "I don't want to send this data"
-msgstr ""
+msgid "I don't want to send anonymous data"
+msgstr "No deseo enviar datos anónimos"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:111
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:118
msgctxt "@text:window"
-msgid "Allow sending this data to Ultimaker and help us improve Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/R2D2/EvaluationSidebar.qml:49
-msgctxt "@label"
-msgid "No print selected"
-msgstr ""
+msgid "Allow sending anonymous data"
+msgstr "Permitir el envío de datos anónimos"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
msgctxt "@title:window"
@@ -2575,19 +2425,19 @@ msgstr "Profundidad (mm)"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:126
msgctxt "@info:tooltip"
-msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
-msgstr "De manera predeterminada, los píxeles blancos representan los puntos altos de la malla y los píxeles negros representan los puntos bajos de la malla. Cambie esta opción para invertir el comportamiento de tal manera que los píxeles negros representen los puntos altos de la malla y los píxeles blancos representen los puntos bajos de la malla."
-
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
-msgctxt "@item:inlistbox"
-msgid "Lighter is higher"
-msgstr "Cuanto más claro más alto"
+msgid "For lithophanes dark pixels should correspond to thicker locations in order to block more light coming through. For height maps lighter pixels signify higher terrain, so lighter pixels should correspond to thicker locations in the generated 3D model."
+msgstr "Para las litofanías, los píxeles oscuros deben coincidir con ubicaciones más gruesas para bloquear la entrada de más luz. En los mapas de altura, los píxeles más claros se corresponden con un terreno más alto, por lo que dichos píxeles deben coincidir con ubicaciones más gruesas en el modelo 3D generado."
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
msgctxt "@item:inlistbox"
msgid "Darker is higher"
msgstr "Cuanto más oscuro más alto"
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
+msgctxt "@item:inlistbox"
+msgid "Lighter is higher"
+msgstr "Cuanto más claro más alto"
+
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:149
msgctxt "@info:tooltip"
msgid "The amount of smoothing to apply to the image."
@@ -2598,70 +2448,69 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Suavizado"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:37
-msgctxt "@label"
-msgid "Mesh Type"
-msgstr "Tipo de malla"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:68
-msgctxt "@label"
-msgid "Normal model"
-msgstr "Modelo normal"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:75
-msgctxt "@label"
-msgid "Print as support"
-msgstr "Imprimir como soporte"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:83
-msgctxt "@label"
-msgid "Don't support overlap with other models"
-msgstr "No crear soporte en otros modelos (por superposición)"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:91
-msgctxt "@label"
-msgid "Modify settings for overlap with other models"
-msgstr "Modificar ajustes de otros modelos (por superposición)"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:99
-msgctxt "@label"
-msgid "Modify settings for infill of other models"
-msgstr "Modificar ajustes del relleno de otros modelos"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
-msgctxt "@action:button"
-msgid "Select settings"
-msgstr "Seleccionar ajustes"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:13
msgctxt "@title:window"
msgid "Select Settings to Customize for this model"
msgstr "Seleccionar ajustes o personalizar este modelo"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:431
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:56
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtrar..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:445
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:70
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Mostrar todo"
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:44
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Tipo de malla"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:85
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Modelo normal"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:97
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Imprimir como soporte"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:109
+msgctxt "@label"
+msgid "Modify settings for overlaps"
+msgstr "Modificar los ajustes de las superposiciones"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:121
+msgctxt "@label"
+msgid "Don't support overlaps"
+msgstr "No es compatible con superposiciones"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:145
+msgctxt "@action:checkbox"
+msgid "Infill only"
+msgstr "Solo relleno"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:368
+msgctxt "@action:button"
+msgid "Select settings"
+msgstr "Seleccionar ajustes"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:14
msgctxt "@title:window"
msgid "Open Project"
msgstr "Abrir proyecto"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:58
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Update/override existing profile"
msgid "Update existing"
msgstr "Actualizar existente"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:59
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Save settings in a new profile"
msgid "Create new"
msgstr "Crear nuevo"
@@ -2688,6 +2537,11 @@ msgctxt "@action:ComboBox option"
msgid "Update"
msgstr "Actualizar"
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
+msgctxt "@action:ComboBox option"
+msgid "Create new"
+msgstr "Crear nuevo"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
@@ -2701,7 +2555,7 @@ msgid "Printer Group"
msgstr "Grupo de impresoras"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:220
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Ajustes del perfil"
@@ -2712,75 +2566,81 @@ msgid "How should the conflict in the profile be resolved?"
msgstr "¿Cómo debería solucionarse el conflicto en el perfil?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:323
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:221
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:244
msgctxt "@action:label"
msgid "Name"
msgstr "Nombre"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:261
+msgctxt "@action:label"
+msgid "Intent"
+msgstr "Intent"
+
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:228
msgctxt "@action:label"
msgid "Not in profile"
msgstr "No está en el perfil"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:210
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:233
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
msgstr[0] "%1 sobrescrito"
msgstr[1] "%1 sobrescritos"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:247
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:262
msgctxt "@action:label"
msgid "Derivative from"
msgstr "Derivado de"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:252
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:267
msgctxt "@action:label"
msgid "%1, %2 override"
msgid_plural "%1, %2 overrides"
msgstr[0] "%1, %2 sobrescrito"
msgstr[1] "%1, %2 sobrescritos"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:268
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:283
msgctxt "@action:label"
msgid "Material settings"
msgstr "Ajustes del material"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:284
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:299
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
msgstr "¿Cómo debería solucionarse el conflicto en el material?"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:342
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Visibilidad de los ajustes"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:336
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:351
msgctxt "@action:label"
msgid "Mode"
msgstr "Modo"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:367
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Ajustes visibles:"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:372
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 de un total de %2"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:383
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:398
msgctxt "@action:warning"
msgid "Loading a project will clear all models on the build plate."
msgstr "Si carga un proyecto, se borrarán todos los modelos de la placa de impresión."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:401
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:416
msgctxt "@action:button"
msgid "Open"
msgstr "Abrir"
@@ -2788,285 +2648,140 @@ msgstr "Abrir"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
msgctxt "@title"
msgid "My Backups"
-msgstr ""
+msgstr "Mis copias de seguridad"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:38
msgctxt "@empty_state"
msgid "You don't have any backups currently. Use the 'Backup Now' button to create one."
-msgstr ""
+msgstr "Actualmente no posee ninguna copia de seguridad. Utilice el botón de Realizar copia de seguridad ahora para crear una."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:60
msgctxt "@backup_limit_info"
msgid "During the preview phase, you'll be limited to 5 visible backups. Remove a backup to see older ones."
-msgstr ""
+msgstr "Durante la fase de vista previa, solo se mostrarán 5 copias de seguridad. Elimine una copia de seguridad para ver copias de seguridad antiguas."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:34
msgctxt "@description"
msgid "Backup and synchronize your Cura settings."
-msgstr ""
+msgstr "Realice una copia de seguridad y sincronice sus ajustes de Cura."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:51
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:138
msgctxt "@button"
msgid "Sign in"
-msgstr ""
+msgstr "Iniciar sesión"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
msgctxt "@title:window"
msgid "Cura Backups"
-msgstr ""
+msgstr "Copias de seguridad de Cura"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
msgctxt "@backuplist:label"
msgid "Cura Version"
-msgstr ""
+msgstr "Versión de Cura"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
msgctxt "@backuplist:label"
msgid "Machines"
-msgstr ""
+msgstr "Máquinas"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
msgctxt "@backuplist:label"
msgid "Materials"
-msgstr ""
+msgstr "Materiales"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
msgctxt "@backuplist:label"
msgid "Profiles"
-msgstr ""
+msgstr "Perfiles"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
msgctxt "@backuplist:label"
msgid "Plugins"
-msgstr ""
+msgstr "Complementos"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
msgctxt "@button"
msgid "Restore"
-msgstr ""
+msgstr "Restaurar"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
msgctxt "@dialog:title"
msgid "Delete Backup"
-msgstr ""
+msgstr "Eliminar copia de seguridad"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:100
msgctxt "@dialog:info"
msgid "Are you sure you want to delete this backup? This cannot be undone."
-msgstr ""
+msgstr "¿Seguro que desea eliminar esta copia de seguridad? Esta acción no se puede deshacer."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:108
msgctxt "@dialog:title"
msgid "Restore Backup"
-msgstr ""
+msgstr "Restaurar copia de seguridad"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:109
msgctxt "@dialog:info"
msgid "You will need to restart Cura before your backup is restored. Do you want to close Cura now?"
-msgstr ""
+msgstr "Deberá reiniciar Cura para restaurar su copia de seguridad. ¿Desea cerrar Cura ahora?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:22
msgctxt "@button"
msgid "Want more?"
-msgstr ""
+msgstr "¿Desea obtener más información?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
msgctxt "@button"
msgid "Backup Now"
-msgstr ""
+msgstr "Realizar copia de seguridad ahora"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
msgctxt "@checkbox:description"
msgid "Auto Backup"
-msgstr ""
+msgstr "Copia de seguridad automática"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:44
msgctxt "@checkbox:description"
msgid "Automatically create a backup each day that Cura is started."
-msgstr ""
+msgstr "Crea una copia de seguridad de forma automática cada día que inicia Cura."
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMainSettingsSelector.qml:75
-msgctxt "@label"
-msgid "Not supported"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:35
-msgctxt "@action:button"
-msgid "Previous"
-msgstr "Anterior"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
-msgctxt "@action:button"
-msgid "Export"
-msgstr "Exportar"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Siguiente"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:169
-msgctxt "@label"
-msgid "Tip"
-msgstr "Consejo"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:160
-msgctxt "@label"
-msgid "Print experiment"
-msgstr "Ensayo de impresión"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageValidation.qml:25
-msgctxt "@label"
-msgid "Checklist"
-msgstr "Lista de verificación"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:26
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:25
-msgctxt "@title"
-msgid "Select Printer Upgrades"
-msgstr "Seleccionar actualizaciones de impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:38
-msgctxt "@label"
-msgid "Please select any upgrades made to this Ultimaker 2."
-msgstr "Seleccione cualquier actualización de este Ultimaker 2."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
-msgctxt "@label"
-msgid "Olsson Block"
-msgstr "Bloque Olsson"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:30
msgctxt "@title"
msgid "Build Plate Leveling"
msgstr "Nivelación de la placa de impresión"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:38
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:44
msgctxt "@label"
msgid "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted."
msgstr "Ahora puede ajustar la placa de impresión para asegurarse de que sus impresiones salgan muy bien. Al hacer clic en 'Mover a la siguiente posición', la tobera se trasladará a las diferentes posiciones que se pueden ajustar."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:57
msgctxt "@label"
msgid "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle."
msgstr "Para cada posición: inserte una hoja de papel debajo de la tobera y ajuste la altura de la placa de impresión. La altura de la placa de impresión es correcta cuando el papel queda ligeramente sujeto por la punta de la tobera."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:62
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:75
msgctxt "@action:button"
msgid "Start Build Plate Leveling"
msgstr "Iniciar nivelación de la placa de impresión"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:74
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:87
msgctxt "@action:button"
msgid "Move to Next Position"
msgstr "Mover a la siguiente posición"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:37
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker Original"
msgstr "Seleccione cualquier actualización de Ultimaker Original"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:45
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:41
msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Placa de impresión caliente (kit oficial o construida por usted mismo)"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
-msgctxt "@title"
-msgid "Check Printer"
-msgstr "Comprobar impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
-msgctxt "@label"
-msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
-msgstr "Es una buena idea hacer un par de comprobaciones en su Ultimaker. Puede omitir este paso si usted sabe que su máquina funciona correctamente"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
-msgctxt "@action:button"
-msgid "Start Printer Check"
-msgstr "Iniciar comprobación de impresora"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
-msgctxt "@label"
-msgid "Connection: "
-msgstr "Conexión: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Connected"
-msgstr "Conectado"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Not connected"
-msgstr "Sin conexión"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
-msgctxt "@label"
-msgid "Min endstop X: "
-msgstr "Parada final mín. en X: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-msgctxt "@info:status"
-msgid "Works"
-msgstr "Funciona"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Not checked"
-msgstr "Sin comprobar"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
-msgctxt "@label"
-msgid "Min endstop Y: "
-msgstr "Parada final mín. en Y: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
-msgctxt "@label"
-msgid "Min endstop Z: "
-msgstr "Parada final mín. en Z: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
-msgctxt "@label"
-msgid "Nozzle temperature check: "
-msgstr "Comprobación de la temperatura de la tobera: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Stop Heating"
-msgstr "Detener calentamiento"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Start Heating"
-msgstr "Iniciar calentamiento"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
-msgctxt "@label"
-msgid "Build plate temperature check:"
-msgstr "Comprobación de la temperatura de la placa de impresión:"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Checked"
-msgstr "Comprobada"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
-msgctxt "@label"
-msgid "Everything is in order! You're done with your CheckUp."
-msgstr "¡Todo correcto! Ha terminado con la comprobación."
-
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
@@ -3117,170 +2832,176 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "¿Está seguro de que desea cancelar la impresión?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
msgctxt "@title"
msgid "Information"
msgstr "Información"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
msgctxt "@title:window"
msgid "Confirm Diameter Change"
msgstr "Confirmar cambio de diámetro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:102
msgctxt "@label (%1 is a number)"
msgid "The new filament diameter is set to %1 mm, which is not compatible with the current extruder. Do you wish to continue?"
msgstr "El nuevo diámetro del filamento está ajustado en %1 mm y no es compatible con el extrusor actual. ¿Desea continuar?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:128
msgctxt "@label"
msgid "Display Name"
msgstr "Mostrar nombre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:138
msgctxt "@label"
msgid "Brand"
msgstr "Marca"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:148
msgctxt "@label"
msgid "Material Type"
msgstr "Tipo de material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:158
msgctxt "@label"
msgid "Color"
msgstr "Color"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:208
msgctxt "@label"
msgid "Properties"
msgstr "Propiedades"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:214
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:210
msgctxt "@label"
msgid "Density"
msgstr "Densidad"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:229
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:225
msgctxt "@label"
msgid "Diameter"
msgstr "Diámetro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:259
msgctxt "@label"
msgid "Filament Cost"
msgstr "Coste del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:276
msgctxt "@label"
msgid "Filament weight"
-msgstr "Anchura del filamento"
+msgstr "Peso del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:294
msgctxt "@label"
msgid "Filament length"
msgstr "Longitud del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:307
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:303
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Coste por metro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:317
msgctxt "@label"
msgid "This material is linked to %1 and shares some of its properties."
msgstr "Este material está vinculado a %1 y comparte alguna de sus propiedades."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:324
msgctxt "@label"
msgid "Unlink Material"
msgstr "Desvincular material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:339
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:335
msgctxt "@label"
msgid "Description"
msgstr "Descripción"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:352
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:348
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Información sobre adherencia"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:17
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
msgctxt "@label"
msgid "Print settings"
msgstr "Ajustes de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:84
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:84
msgctxt "@action:button"
msgid "Activate"
msgstr "Activar"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:126
msgctxt "@action:button"
msgid "Create"
msgstr "Crear"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:140
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Duplicado"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:141
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:167
msgctxt "@action:button"
msgid "Import"
msgstr "Importar"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:203
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:179
+msgctxt "@action:button"
+msgid "Export"
+msgstr "Exportar"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:233
msgctxt "@action:label"
msgid "Printer"
msgstr "Impresora"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:262
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:274
msgctxt "@title:window"
msgid "Confirm Remove"
msgstr "Confirmar eliminación"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:263
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:247
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:300
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:275
msgctxt "@label (%1 is object name)"
msgid "Are you sure you wish to remove %1? This cannot be undone!"
msgstr "¿Seguro que desea eliminar %1? ¡Esta acción no se puede deshacer!"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:277
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:285
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:322
msgctxt "@title:window"
msgid "Import Material"
msgstr "Importar material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:323
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Could not import material %1: %2"
msgstr "No se pudo importar el material en %1: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:327
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully imported material %1"
msgstr "El material se ha importado correctamente en %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:316
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:345
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:353
msgctxt "@title:window"
msgid "Export Material"
msgstr "Exportar material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:357
msgctxt "@info:status Don't translate the XML tags and !"
msgid "Failed to export material to %1: %2"
msgstr "Se ha producido un error al exportar el material a %1: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:363
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "El material se ha exportado correctamente a %1"
@@ -3295,415 +3016,425 @@ msgctxt "@label:textbox"
msgid "Check all"
msgstr "Comprobar todo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:47
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:61
msgctxt "@info:status"
msgid "Calculated"
msgstr "Calculado"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:75
msgctxt "@title:column"
msgid "Setting"
msgstr "Ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
msgctxt "@title:column"
msgid "Profile"
msgstr "Perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:74
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:89
msgctxt "@title:column"
msgid "Current"
msgstr "Actual"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:97
msgctxt "@title:column"
msgid "Unit"
msgstr "Unidad"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr "General"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:126
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:132
msgctxt "@label"
msgid "Interface"
msgstr "Interfaz"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:143
msgctxt "@label"
msgid "Language:"
msgstr "Idioma:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:210
msgctxt "@label"
msgid "Currency:"
msgstr "Moneda:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:223
msgctxt "@label"
msgid "Theme:"
msgstr "Tema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:273
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:279
msgctxt "@label"
msgid "You will need to restart the application for these changes to have effect."
msgstr "Tendrá que reiniciar la aplicación para que estos cambios tengan efecto."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:296
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Segmentar automáticamente al cambiar los ajustes."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Segmentar automáticamente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:312
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportamiento de la ventanilla"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
msgctxt "@info:tooltip"
msgid "Highlight unsupported areas of the model in red. Without support these areas will not print properly."
msgstr "Resaltar en rojo las áreas del modelo sin soporte. Sin soporte, estas áreas no se imprimirán correctamente."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:335
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Mostrar voladizos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:343
msgctxt "@info:tooltip"
msgid "Moves the camera so the model is in the center of the view when a model is selected"
msgstr "Mueve la cámara de manera que el modelo se encuentre en el centro de la vista cuando se selecciona un modelo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:348
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr "Centrar cámara cuando se selecciona elemento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "¿Se debería invertir el comportamiento predeterminado del zoom de cura?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:355
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Invertir la dirección del zoom de la cámara."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr "¿Debería moverse el zoom en la dirección del ratón?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
+msgctxt "@info:tooltip"
+msgid "Zooming towards the mouse is not supported in the orthographic perspective."
+msgstr "Hacer zoom en la dirección del ratón no es compatible con la perspectiva ortográfica."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Hacer zoom en la dirección del ratón"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:380
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:410
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved so that they no longer intersect?"
msgstr "¿Deben moverse los modelos en la plataforma de modo que no se crucen?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:385
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
msgctxt "@option:check"
msgid "Ensure models are kept apart"
-msgstr "Asegúrese de que lo modelos están separados"
+msgstr "Asegúrese de que los modelos están separados"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:394
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:424
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved down to touch the build plate?"
msgstr "¿Deben moverse los modelos del área de impresión de modo que no toquen la placa de impresión?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:429
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr "Arrastrar modelos a la placa de impresión de forma automática"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:411
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr "Se muestra el mensaje de advertencia en el lector de GCode."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr "Mensaje de advertencia en el lector de GCode"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:428
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:458
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "¿Debe forzarse el modo de compatibilidad de la capa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:463
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr "Forzar modo de compatibilidad de la vista de capas (necesario reiniciar)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
+msgctxt "@info:tooltip"
+msgid "Should Cura open at the location it was closed?"
+msgstr "¿Debería abrirse Cura en el lugar donde se cerró?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
+msgctxt "@option:check"
+msgid "Restore window position on start"
+msgstr "Restaurar la posición de la ventana al inicio"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:488
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr "¿Qué tipo de renderizado de cámara debería usarse?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:495
+msgctxt "@window:text"
+msgid "Camera rendering:"
+msgstr "Renderizado de cámara:"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+msgid "Perspective"
+msgstr "Perspectiva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+msgid "Orthographic"
+msgstr "Ortográfica"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Abrir y guardar archivos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:456
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:545
msgctxt "@info:tooltip"
msgid "Should models be scaled to the build volume if they are too large?"
msgstr "¿Deben ajustarse los modelos al volumen de impresión si son demasiado grandes?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:461
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:550
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Escalar modelos de gran tamaño"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:560
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Un modelo puede mostrarse demasiado pequeño si su unidad son metros en lugar de milímetros, por ejemplo. ¿Deben escalarse estos modelos?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:565
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Escalar modelos demasiado pequeños"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr "¿Se deberían seleccionar los modelos después de haberse cargado?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:491
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:580
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr "Seleccionar modelos al abrirlos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
msgctxt "@info:tooltip"
msgid "Should a prefix based on the printer name be added to the print job name automatically?"
msgstr "¿Debe añadirse automáticamente un prefijo basado en el nombre de la impresora al nombre del trabajo de impresión?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr "Agregar prefijo de la máquina al nombre del trabajo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:516
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:605
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr "¿Mostrar un resumen al guardar un archivo de proyecto?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:609
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr "Mostrar un cuadro de diálogo de resumen al guardar el proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Comportamiento predeterminado al abrir un archivo del proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:627
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Comportamiento predeterminado al abrir un archivo del proyecto: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Preguntar siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:642
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Abrir siempre como un proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:554
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Importar modelos siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:679
msgctxt "@info:tooltip"
msgid "When you have made changes to a profile and switched to a different one, a dialog will be shown asking whether you want to keep your modifications or not, or you can choose a default behaviour and never show that dialog again."
msgstr "Si ha realizado cambios en un perfil y, a continuación, ha cambiado a otro, aparecerá un cuadro de diálogo que le preguntará si desea guardar o descartar los cambios. También puede elegir el comportamiento predeterminado, así ese cuadro de diálogo no volverá a aparecer."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:599
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:52
msgctxt "@label"
msgid "Profiles"
msgstr "Perfiles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:693
msgctxt "@window:text"
msgid "Default behavior for changed setting values when switching to a different profile: "
msgstr "Comportamiento predeterminado para los valores modificados al cambiar a otro perfil: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:707
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:157
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Preguntar siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Descartar siempre los ajustes modificados"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:709
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr "Transferir siempre los ajustes modificados al nuevo perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:654
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
msgctxt "@label"
msgid "Privacy"
msgstr "Privacidad"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:661
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:750
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr "¿Debe Cura buscar actualizaciones cuando se abre el programa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:666
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:755
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Buscar actualizaciones al iniciar"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:676
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:765
msgctxt "@info:tooltip"
msgid "Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored."
msgstr "¿Deben enviarse datos anónimos sobre la impresión a Ultimaker? Tenga en cuenta que no se envían ni almacenan modelos, direcciones IP ni otra información de identificación personal."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:681
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:770
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Enviar información (anónima) de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:690
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:779
msgctxt "@action:button"
msgid "More information"
msgstr "Más información"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
-msgctxt "@label"
-msgid "Experimental"
-msgstr "Experimental"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:715
-msgctxt "@info:tooltip"
-msgid "Use multi build plate functionality"
-msgstr "Utilizar funcionalidad de placa de impresión múltiple"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
-msgctxt "@option:check"
-msgid "Use multi build plate functionality (restart required)"
-msgstr "Utilizar funcionalidad de placa de impresión múltiple (reinicio requerido)"
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:16
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr "Impresoras"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:57
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:63
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
msgctxt "@action:button"
msgid "Rename"
msgstr "Cambiar nombre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:363
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:419
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Perfiles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:104
msgctxt "@label"
msgid "Create"
msgstr "Crear"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@label"
msgid "Duplicate"
msgstr "Duplicado"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:202
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Crear perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:176
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:204
msgctxt "@info"
msgid "Please provide a name for this profile."
-msgstr ""
+msgstr "Introduzca un nombre para este perfil."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:260
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Duplicar perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:291
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Cambiar nombre de perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:276
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:304
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Importar perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:333
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Exportar perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:396
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Impresora: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Default profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Custom profiles"
-msgstr "Perfiles personalizados"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:554
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr "Actualizar perfil con ajustes o sobrescrituras actuales"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:561
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:257
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Descartar cambios actuales"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:514
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:580
msgctxt "@action:label"
msgid "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below."
msgstr "Este perfil utiliza los ajustes predeterminados especificados por la impresora, por eso no aparece ningún ajuste o sobrescritura en la lista que se ve a continuación."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:521
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:588
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr "Los ajustes actuales coinciden con el perfil seleccionado."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:606
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Ajustes globales"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:90
msgctxt "@action:button"
msgid "Marketplace"
-msgstr ""
+msgstr "Marketplace"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
@@ -3726,7 +3457,7 @@ msgstr "&Ver"
#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
msgctxt "@title:menu menubar:toplevel"
msgid "&Settings"
-msgstr ""
+msgstr "A&justes"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
msgctxt "@title:menu menubar:toplevel"
@@ -3743,12 +3474,12 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "A&yuda"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
msgctxt "@title:window"
msgid "New project"
msgstr "Nuevo proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:125
msgctxt "@info:question"
msgid "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings."
msgstr "¿Está seguro de que desea iniciar un nuevo proyecto? Esto borrará la placa de impresión y cualquier ajuste no guardado."
@@ -3760,36 +3491,36 @@ msgstr "Sin título"
#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "search settings"
-msgstr ""
+msgid "Search settings"
+msgstr "Buscar ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:462
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Copiar valor en todos los extrusores"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:474
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:471
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr "Copiar todos los valores cambiados en todos los extrusores"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Ocultar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:521
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "No mostrar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Mostrar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:557
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configurar visibilidad de los ajustes..."
@@ -3805,27 +3536,32 @@ msgstr ""
"\n"
"Haga clic para mostrar estos ajustes."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:81
+msgctxt "@label"
+msgid "This setting is not used because all the settings that it influences are overridden."
+msgstr "Este ajuste no se utiliza porque los ajustes a los que afecta están sobrescritos."
+
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:86
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Afecta a"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:91
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Afectado por"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:166
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:187
msgctxt "@label"
msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders."
msgstr "Este ajuste siempre se comparte entre extrusores. Si lo modifica, modificará el valor de todos los extrusores."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:191
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr "El valor se resuelve según los valores de los extrusores. "
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:230
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3836,7 +3572,7 @@ msgstr ""
"\n"
"Haga clic para restaurar el valor del perfil."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:329
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3847,87 +3583,79 @@ msgstr ""
"\n"
"Haga clic para restaurar el valor calculado."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/NoIntentIcon.qml:31
+msgctxt "@label %1 is filled in with the type of a profile. %2 is filled with a list of numbers (eg '1' or '1, 2')"
+msgid "There is no %1 profile for the configuration in extruder %2. The default intent will be used instead"
+msgid_plural "There is no %1 profile for the configurations in extruders %2. The default intent will be used instead"
+msgstr[0] ""
+msgstr[1] ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
msgctxt "@button"
msgid "Recommended"
-msgstr ""
+msgstr "Recomendado"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
msgctxt "@button"
msgid "Custom"
-msgstr ""
+msgstr "Personalizado"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
msgctxt "@label"
msgid "Gradual infill"
-msgstr ""
+msgstr "Relleno gradual"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:232
msgctxt "@label"
msgid "Gradual infill will gradually increase the amount of infill towards the top."
msgstr "Un relleno gradual aumentará gradualmente la cantidad de relleno hacia arriba."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:29
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:30
msgctxt "@label"
msgid "Support"
-msgstr ""
+msgstr "Soporte"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:71
msgctxt "@label"
msgid "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."
msgstr "Generar estructuras para soportar piezas del modelo que tengan voladizos. Sin estas estructuras, estas piezas se romperían durante la impresión."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:136
-msgctxt "@label"
-msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
-msgstr "Seleccione qué extrusor se utilizará como soporte. Esta opción formará estructuras de soporte por debajo del modelo para evitar que éste se combe o la impresión se haga en el aire."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:29
msgctxt "@label"
msgid "Adhesion"
-msgstr ""
+msgstr "Adherencia"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:74
msgctxt "@label"
msgid "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."
msgstr "Habilita la impresión de un borde o una balsa. Esta opción agregará un área plana alrededor del objeto, que es fácil de cortar después."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:175
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Altura de capa"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:206
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:81
msgctxt "@tooltip"
msgid "You have modified some profile settings. If you want to change these go to custom mode."
msgstr "Ha modificado algunos ajustes del perfil. Si desea cambiarlos, hágalo en el modo personalizado."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:355
-msgctxt "@tooltip"
-msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:449
-msgctxt "@tooltip"
-msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
-msgstr "Hay un perfil personalizado activado en este momento. Para habilitar el control deslizante de calidad, seleccione un perfil de calidad predeterminado en la pestaña Personalizado"
-
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:13
msgctxt "@label:Should be short"
msgid "On"
-msgstr ""
+msgstr "Encendido"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
msgctxt "@label:Should be short"
msgid "Off"
-msgstr ""
+msgstr "Apagado"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:33
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Experimental"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:47
msgctxt "@label"
msgid "Profile"
-msgstr ""
+msgstr "Perfil"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:172
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3938,10 +3666,15 @@ msgstr ""
"\n"
"Haga clic para abrir el administrador de perfiles."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:160
+msgctxt "@label:header"
+msgid "Custom profiles"
+msgstr "Perfiles personalizados"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:21
msgctxt "@label shown when we load a Gcode file"
-msgid "Print setup disabled. G code file can not be modified."
-msgstr ""
+msgid "Print setup disabled. G-code file can not be modified."
+msgstr "Configuración de impresión deshabilitada. No se puede modificar el archivo GCode."
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
@@ -3973,59 +3706,59 @@ msgctxt "@label"
msgid "Send G-code"
msgstr "Enviar GCode"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:364
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:365
msgctxt "@tooltip of G-code command input"
msgid "Send a custom G-code command to the connected printer. Press 'enter' to send the command."
msgstr "Envíe un comando de GCode personalizado a la impresora conectada. Pulse «Intro» para enviar el comando."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:41
msgctxt "@label"
msgid "Extruder"
msgstr "Extrusor"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:71
msgctxt "@tooltip"
msgid "The target temperature of the hotend. The hotend will heat up or cool down towards this temperature. If this is 0, the hotend heating is turned off."
msgstr "Temperatura objetivo del extremo caliente. El extremo caliente se calentará o enfriará en función de esta temperatura. Si el valor es 0, el calentamiento del extremo caliente se desactivará."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:103
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr "Temperatura actual de este extremo caliente."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:177
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr "Temperatura a la que se va a precalentar el extremo caliente."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:332
msgctxt "@button Cancel pre-heating"
msgid "Cancel"
msgstr "Cancelar"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:344
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:335
msgctxt "@button"
msgid "Pre-heat"
msgstr "Precalentar"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:370
msgctxt "@tooltip of pre-heat"
msgid "Heat the hotend in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the hotend to heat up when you're ready to print."
msgstr "Caliente el extremo caliente antes de imprimir. Puede continuar ajustando la impresión durante el calentamiento, así no tendrá que esperar a que el extremo caliente se caliente para poder imprimir."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:406
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr "Color del material en este extrusor."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:438
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Material en este extrusor."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:470
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Tobera insertada en este extrusor."
@@ -4065,12 +3798,12 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:46
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Favoritos"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:71
msgctxt "@label:category menu label"
msgid "Generic"
msgstr "Genérico"
@@ -4090,42 +3823,47 @@ msgctxt "@title:menu menubar:settings"
msgid "&Printer"
msgstr "&Impresora"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:26
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:27
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:36
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Definir como extrusor activo"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Enable Extruder"
msgstr "Habilitar extrusor"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:49
msgctxt "@action:inmenu"
msgid "Disable Extruder"
msgstr "Deshabilitar extrusor"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:62
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "&Placa de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:65
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Perfil"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:19
msgctxt "@action:inmenu menubar:view"
msgid "&Camera position"
msgstr "&Posición de la cámara"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:44
+msgctxt "@action:inmenu menubar:view"
+msgid "Camera view"
+msgstr "Vista de cámara"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:47
+msgctxt "@action:inmenu menubar:view"
+msgid "Perspective"
+msgstr "Perspectiva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:59
+msgctxt "@action:inmenu menubar:view"
+msgid "Orthographic"
+msgstr "Ortográfica"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:80
msgctxt "@action:inmenu menubar:view"
msgid "&Build plate"
msgstr "P&laca de impresión"
@@ -4145,17 +3883,17 @@ msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Gestionar visibilidad de los ajustes..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:33
msgctxt "@title:menu menubar:file"
msgid "&Save..."
msgstr "&Guardar..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:54
msgctxt "@title:menu menubar:file"
msgid "&Export..."
msgstr "&Exportar..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:65
msgctxt "@action:inmenu menubar:file"
msgid "Export Selection..."
msgstr "Exportar selección..."
@@ -4182,190 +3920,193 @@ msgstr "Número de copias"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
msgctxt "@header"
msgid "Configurations"
-msgstr ""
+msgstr "Configuraciones"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:112
msgctxt "@label"
msgid "Select configuration"
-msgstr ""
+msgstr "Seleccionar configuración"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:201
-msgctxt "@label"
-msgid "See the material compatibility chart"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:274
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:223
msgctxt "@label"
msgid "Configurations"
-msgstr ""
+msgstr "Configuraciones"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
msgctxt "@label"
msgid "Loading available configurations from the printer..."
-msgstr ""
+msgstr "Cargando configuraciones disponibles desde la impresora..."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:58
msgctxt "@label"
msgid "The configurations are not available because the printer is disconnected."
-msgstr ""
+msgstr "Las configuraciones no se encuentran disponibles porque la impresora no está conectada."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:25
msgctxt "@header"
msgid "Custom"
-msgstr ""
+msgstr "Personalizado"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
msgctxt "@label"
msgid "Printer"
-msgstr ""
+msgstr "Impresora"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:202
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
msgctxt "@label"
msgid "Enabled"
-msgstr ""
+msgstr "Habilitado"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:251
msgctxt "@label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:344
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:378
msgctxt "@label"
msgid "Use glue for better adhesion with this material combination."
-msgstr ""
+msgstr "Utilice pegamento con esta combinación de materiales para lograr una mejor adhesión."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:128
msgctxt "@label"
msgid "This configuration is not available because %1 is not recognized. Please visit %2 to download the correct material profile."
-msgstr ""
+msgstr "Esta configuración no se encuentra disponible porque %1 es un perfil desconocido. Visite %2 para descargar el perfil de materiales correcto."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:129
msgctxt "@label"
msgid "Marketplace"
-msgstr ""
+msgstr "Marketplace"
#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:15
msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr "Abrir &reciente"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr "Activar impresión"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr "Nombre del trabajo"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Tiempo de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:169
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr "Tiempo restante estimado"
#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
msgctxt "@label"
-msgid "View types"
-msgstr ""
+msgid "View type"
+msgstr "Ver tipo"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
msgctxt "@label"
-msgid "Hi "
-msgstr ""
+msgid "Object list"
+msgstr "Lista de objetos"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:22
+msgctxt "@label The argument is a username."
+msgid "Hi %1"
+msgstr "Hola, %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:33
msgctxt "@button"
msgid "Ultimaker account"
-msgstr ""
+msgstr "Cuenta de Ultimaker"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
msgctxt "@button"
msgid "Sign out"
-msgstr ""
+msgstr "Cerrar sesión"
#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
msgctxt "@action:button"
msgid "Sign in"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:29
-msgctxt "@label"
-msgid "Ultimaker Cloud"
-msgstr ""
+msgstr "Iniciar sesión"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
msgctxt "@label"
msgid "The next generation 3D printing workflow"
-msgstr ""
+msgstr "El flujo de trabajo de impresión 3D de próxima generación"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:51
msgctxt "@text"
msgid ""
"- Send print jobs to Ultimaker printers outside your local network\n"
"- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
-"- Get exclusive access to material profiles from leading brands"
+"- Get exclusive access to print profiles from leading brands"
msgstr ""
+"- Envíe trabajos de impresión a impresoras Ultimaker fuera de su red local\n"
+"- Guarde su configuración de Ultimaker Cura en la nube para poder usarla en cualquier lugar\n"
+"- Disfrute de acceso exclusivo a perfiles de impresión de marcas líderes"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
msgctxt "@button"
msgid "Create account"
-msgstr ""
+msgstr "Crear cuenta"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
msgctxt "@label"
msgid "No time estimation available"
-msgstr ""
+msgstr "Ningún cálculo de tiempo disponible"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:76
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
msgctxt "@label"
msgid "No cost estimation available"
-msgstr ""
+msgstr "Ningún cálculo de costes disponible"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
msgctxt "@button"
msgid "Preview"
-msgstr ""
+msgstr "Vista previa"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:55
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Segmentando..."
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:61
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:67
msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
+msgid "Unable to slice"
msgstr "No se puede segmentar"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:116
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
+msgctxt "@button"
+msgid "Processing"
+msgstr "Procesando"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
msgctxt "@button"
msgid "Slice"
-msgstr ""
+msgstr "Segmentación"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
msgctxt "@label"
msgid "Start the slicing process"
-msgstr ""
+msgstr "Iniciar el proceso de segmentación"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
msgctxt "@button"
msgid "Cancel"
-msgstr ""
+msgstr "Cancelar"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
msgctxt "@label"
-msgid "Time specification"
-msgstr ""
+msgid "Time estimation"
+msgstr "Estimación de tiempos"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
msgctxt "@label"
-msgid "Material specification"
-msgstr ""
+msgid "Material estimation"
+msgstr "Estimación de material"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
msgctxt "@label m for meter"
@@ -4380,292 +4121,306 @@ msgstr "%1 g"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Connected printers"
-msgstr ""
+msgstr "Impresoras conectadas"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Preset printers"
-msgstr ""
+msgstr "Impresoras preconfiguradas"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
msgctxt "@button"
msgid "Add printer"
-msgstr ""
+msgstr "Agregar impresora"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:173
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
msgctxt "@button"
msgid "Manage printers"
-msgstr ""
+msgstr "Administrar impresoras"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
msgctxt "@action:inmenu"
msgid "Show Online Troubleshooting Guide"
-msgstr ""
+msgstr "Mostrar Guía de resolución de problemas en línea"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr "Alternar pantalla completa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
+msgctxt "@action:inmenu"
+msgid "Exit Full Screen"
+msgstr "Salir de modo de pantalla completa"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:103
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "Des&hacer"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:113
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "&Rehacer"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:123
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Salir"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:131
msgctxt "@action:inmenu menubar:view"
msgid "3D View"
msgstr "Vista en 3D"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:138
msgctxt "@action:inmenu menubar:view"
msgid "Front View"
msgstr "Vista frontal"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:145
msgctxt "@action:inmenu menubar:view"
msgid "Top View"
msgstr "Vista superior"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:152
msgctxt "@action:inmenu menubar:view"
msgid "Left Side View"
msgstr "Vista del lado izquierdo"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:159
msgctxt "@action:inmenu menubar:view"
msgid "Right Side View"
msgstr "Vista del lado derecho"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Configurar Cura..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:173
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Agregar impresora..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:179
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Adm&inistrar impresoras ..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Administrar materiales..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195
msgctxt "@action:inmenu menubar:profile"
msgid "&Update profile with current settings/overrides"
msgstr "&Actualizar perfil con ajustes o sobrescrituras actuales"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:192
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Descartar cambios actuales"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr "&Crear perfil a partir de ajustes o sobrescrituras actuales..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Administrar perfiles..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:229
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Mostrar &documentación en línea"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:237
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Informar de un &error"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:245
+msgctxt "@action:inmenu menubar:help"
+msgid "What's New"
+msgstr "Novedades"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
msgctxt "@action:inmenu menubar:help"
msgid "About..."
msgstr "Acerca de..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:258
msgctxt "@action:inmenu menubar:edit"
msgid "Delete Selected Model"
msgid_plural "Delete Selected Models"
msgstr[0] "Eliminar modelo seleccionado"
msgstr[1] "Eliminar modelos seleccionados"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
msgctxt "@action:inmenu menubar:edit"
msgid "Center Selected Model"
msgid_plural "Center Selected Models"
msgstr[0] "Centrar modelo seleccionado"
msgstr[1] "Centrar modelos seleccionados"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
msgctxt "@action:inmenu menubar:edit"
msgid "Multiply Selected Model"
msgid_plural "Multiply Selected Models"
msgstr[0] "Multiplicar modelo seleccionado"
msgstr[1] "Multiplicar modelos seleccionados"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Eliminar modelo"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:294
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Ce&ntrar modelo en plataforma"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:283
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:300
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "A&grupar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:303
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:320
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Desagrupar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:313
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "Co&mbinar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "&Multiplicar modelo..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:347
msgctxt "@action:inmenu menubar:edit"
msgid "Select All Models"
msgstr "Seleccionar todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:357
msgctxt "@action:inmenu menubar:edit"
msgid "Clear Build Plate"
msgstr "Borrar placa de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:367
msgctxt "@action:inmenu menubar:file"
msgid "Reload All Models"
msgstr "Recargar todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:376
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models To All Build Plates"
msgstr "Organizar todos los modelos en todas las placas de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:383
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Organizar todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:391
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Organizar selección"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:381
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:398
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr "Restablecer las posiciones de todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:405
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Transformations"
msgstr "Restablecer las transformaciones de todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:412
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Abrir archivo(s)..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:420
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Nuevo proyecto..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:427
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Mostrar carpeta de configuración"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
msgid "&Marketplace"
-msgstr ""
+msgstr "&Marketplace"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:181
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
msgctxt "@label"
msgid "This package will be installed after restarting."
msgstr "Este paquete se instalará después de reiniciar."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:538
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Cerrando Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:487
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:499
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:551
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr "¿Seguro que desea salir de Cura?"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:589
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:19
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Abrir archivo(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:632
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:695
msgctxt "@window:title"
msgid "Install Package"
msgstr "Instalar paquete"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:640
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:703
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Abrir archivo(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:643
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:706
msgctxt "@text:window"
msgid "We have found one or more G-Code files within the files you have selected. You can only open one G-Code file at a time. If you want to open a G-Code file, please just select only one."
msgstr "Hemos encontrado uno o más archivos de GCode entre los archivos que ha seleccionado. Solo puede abrir los archivos GCode de uno en uno. Si desea abrir un archivo GCode, seleccione solo uno."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:713
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:18
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:809
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Agregar impresora"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:817
+msgctxt "@title:window"
+msgid "What's New"
+msgstr "Novedades"
+
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
msgctxt "@label %1 is filled in with the name of an extruder"
msgid "Print Selected Model with %1"
@@ -4727,50 +4482,22 @@ msgctxt "@action:button"
msgid "Create New Profile"
msgstr "Crear nuevo perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:78
-msgctxt "@title:tab"
-msgid "Add a printer to Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:92
-msgctxt "@title:tab"
-msgid ""
-"Select the printer you want to use from the list below.\n"
-"\n"
-"If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:249
-msgctxt "@label"
-msgid "Manufacturer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:271
-msgctxt "@label"
-msgid "Printer Name"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:294
-msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Agregar impresora"
-
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:15
msgctxt "@title:window"
msgid "About Cura"
msgstr "Acerca de Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:56
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:57
msgctxt "@label"
msgid "version: %1"
msgstr "versión: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:72
msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing."
msgstr "Solución completa para la impresión 3D de filamento fundido."
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:85
msgctxt "@info:credit"
msgid ""
"Cura is developed by Ultimaker B.V. in cooperation with the community.\n"
@@ -4779,122 +4506,122 @@ msgstr ""
"Ultimaker B.V. ha desarrollado Cura en cooperación con la comunidad.\n"
"Cura se enorgullece de utilizar los siguientes proyectos de código abierto:"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
msgctxt "@label"
msgid "Graphical user interface"
msgstr "Interfaz gráfica de usuario (GUI)"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
msgctxt "@label"
msgid "Application framework"
msgstr "Entorno de la aplicación"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
msgctxt "@label"
msgid "G-code generator"
msgstr "Generador de GCode"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:138
msgctxt "@label"
msgid "Interprocess communication library"
msgstr "Biblioteca de comunicación entre procesos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
msgctxt "@label"
msgid "Programming language"
msgstr "Lenguaje de programación"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
msgctxt "@label"
msgid "GUI framework"
msgstr "Entorno de la GUI"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
msgctxt "@label"
msgid "GUI framework bindings"
msgstr "Enlaces del entorno de la GUI"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
msgctxt "@label"
msgid "C/C++ Binding library"
msgstr "Biblioteca de enlaces C/C++"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
msgctxt "@label"
msgid "Data interchange format"
msgstr "Formato de intercambio de datos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
msgctxt "@label"
msgid "Support library for scientific computing"
msgstr "Biblioteca de apoyo para cálculos científicos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
msgctxt "@label"
msgid "Support library for faster math"
msgstr "Biblioteca de apoyo para cálculos más rápidos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
msgctxt "@label"
msgid "Support library for handling STL files"
msgstr "Biblioteca de apoyo para gestionar archivos STL"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
msgctxt "@label"
msgid "Support library for handling planar objects"
msgstr "Biblioteca de compatibilidad para trabajar con objetos planos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
msgctxt "@label"
msgid "Support library for handling triangular meshes"
msgstr "Biblioteca de compatibilidad para trabajar con mallas triangulares"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
msgctxt "@label"
msgid "Support library for analysis of complex networks"
msgstr "Biblioteca de compatibilidad para analizar redes complejas"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
msgctxt "@label"
msgid "Support library for handling 3MF files"
msgstr "Biblioteca de compatibilidad para trabajar con archivos 3MF"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
msgctxt "@label"
msgid "Support library for file metadata and streaming"
msgstr "Biblioteca de compatibilidad para metadatos y transmisión de archivos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
msgctxt "@label"
msgid "Serial communication library"
msgstr "Biblioteca de comunicación en serie"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
msgctxt "@label"
msgid "ZeroConf discovery library"
msgstr "Biblioteca de detección para Zeroconf"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
msgctxt "@label"
msgid "Polygon clipping library"
msgstr "Biblioteca de recorte de polígonos"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:156
msgctxt "@Label"
msgid "Python HTTP library"
msgstr "Biblioteca HTTP de Python"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
msgctxt "@label"
msgid "Font"
msgstr "Fuente"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
msgctxt "@label"
msgid "SVG icons"
msgstr "Iconos SVG"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:160
msgctxt "@label"
msgid "Linux cross-distribution application deployment"
msgstr "Implementación de la aplicación de distribución múltiple de Linux"
@@ -4914,27 +4641,27 @@ msgctxt "@title:window"
msgid "Save Project"
msgstr "Guardar proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:138
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Placa de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:177
msgctxt "@action:label"
msgid "Extruder %1"
msgstr "Extrusor %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:192
msgctxt "@action:label"
msgid "%1 & material"
msgstr "%1 y material"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:243
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:194
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:label"
msgid "Don't show project summary on save again"
msgstr "No mostrar resumen de proyecto al guardar de nuevo"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:262
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:302
msgctxt "@action:button"
msgid "Save"
msgstr "Guardar"
@@ -4964,30 +4691,1451 @@ msgctxt "@action:button"
msgid "Import models"
msgstr "Importar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:210
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Ver solo placa de impresión actual"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
+msgctxt "@label"
+msgid "Empty"
+msgstr "Vacío"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:226
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "Organizar todas las placas de impresión"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
+msgctxt "@label"
+msgid "Add a printer"
+msgstr "Agregar una impresora"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:246
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "Organizar placa de impresión actual"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
+msgctxt "@label"
+msgid "Add a networked printer"
+msgstr "Agregar una impresora en red"
-#: X3GWriter/plugin.json
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
+msgctxt "@label"
+msgid "Add a non-networked printer"
+msgstr "Agregar una impresora fuera de red"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:70
+msgctxt "@label"
+msgid "Add printer by IP address"
+msgstr "Agregar impresora por dirección IP"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:133
+msgctxt "@text"
+msgid "Place enter your printer's IP address."
+msgstr "Introduzca la dirección IP de su impresora."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Agregar"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:204
+msgctxt "@label"
+msgid "Could not connect to device."
+msgstr "No se ha podido conectar al dispositivo."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:208
+msgctxt "@label"
+msgid "The printer at this address has not responded yet."
+msgstr "La impresora todavía no ha respondido en esta dirección."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:240
+msgctxt "@label"
+msgid "This printer cannot be added because it's an unknown printer or it's not the host of a group."
+msgstr "No se puede agregar la impresora porque es desconocida o no aloja un grupo."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:329
+msgctxt "@button"
+msgid "Back"
+msgstr "Atrás"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:342
+msgctxt "@button"
+msgid "Connect"
+msgstr "Conectar"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/FirstStartMachineActionsContent.qml:77
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:123
+msgctxt "@button"
+msgid "Next"
+msgstr "Siguiente"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:23
+msgctxt "@label"
+msgid "User Agreement"
+msgstr "Acuerdo de usuario"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:56
+msgctxt "@button"
+msgid "Agree"
+msgstr "Estoy de acuerdo"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:70
+msgctxt "@button"
+msgid "Decline and close"
+msgstr "Rechazar y cerrar"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:24
+msgctxt "@label"
+msgid "Help us to improve Ultimaker Cura"
+msgstr "Ayúdenos a mejorar Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:57
+msgctxt "@text"
+msgid "Ultimaker Cura collects anonymous data to improve print quality and user experience, including:"
+msgstr "Ultimaker Cura recopila datos anónimos para mejorar la calidad de impresión y la experiencia de usuario, entre otros:"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:71
+msgctxt "@text"
+msgid "Machine types"
+msgstr "Tipos de máquina"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:77
+msgctxt "@text"
+msgid "Material usage"
+msgstr "Uso de material"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:83
+msgctxt "@text"
+msgid "Number of slices"
+msgstr "Número de segmentos"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:89
+msgctxt "@text"
+msgid "Print settings"
+msgstr "Ajustes de impresión"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:102
+msgctxt "@text"
+msgid "Data collected by Ultimaker Cura will not contain any personal information."
+msgstr "Los datos recopilados por Ultimaker Cura no contendrán información personal."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:103
+msgctxt "@text"
+msgid "More information"
+msgstr "Más información"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WhatsNewContent.qml:24
+msgctxt "@label"
+msgid "What's new in Ultimaker Cura"
+msgstr "Novedades en Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:42
+msgctxt "@label"
+msgid "There is no printer found over your network."
+msgstr "No se ha encontrado ninguna impresora en su red."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:179
+msgctxt "@label"
+msgid "Refresh"
+msgstr "Actualizar"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:190
+msgctxt "@label"
+msgid "Add printer by IP"
+msgstr "Agregar impresora por IP"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:223
+msgctxt "@label"
+msgid "Troubleshooting"
+msgstr "Solución de problemas"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:211
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Nombre de la impresora"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:224
+msgctxt "@text"
+msgid "Please give your printer a name"
+msgstr "Indique un nombre para su impresora"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:36
+msgctxt "@label"
+msgid "Ultimaker Cloud"
+msgstr "Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:77
+msgctxt "@text"
+msgid "The next generation 3D printing workflow"
+msgstr "El flujo de trabajo de impresión 3D de próxima generación"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:94
+msgctxt "@text"
+msgid "- Send print jobs to Ultimaker printers outside your local network"
+msgstr "- Envíe trabajos de impresión a impresoras Ultimaker fuera de su red local"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:97
+msgctxt "@text"
+msgid "- Store your Ultimaker Cura settings in the cloud for use anywhere"
+msgstr "- Guarde su configuración de Ultimaker Cura en la nube para poder usarla en cualquier lugar"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:100
+msgctxt "@text"
+msgid "- Get exclusive access to print profiles from leading brands"
+msgstr "- Disfrute de acceso exclusivo a perfiles de impresión de marcas líderes"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:119
+msgctxt "@button"
+msgid "Finish"
+msgstr "Finalizar"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:128
+msgctxt "@button"
+msgid "Create an account"
+msgstr "Crear una cuenta"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:29
+msgctxt "@label"
+msgid "Welcome to Ultimaker Cura"
+msgstr "Le damos la bienvenida a Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:47
+msgctxt "@text"
+msgid ""
+"Please follow these steps to set up\n"
+"Ultimaker Cura. This will only take a few moments."
+msgstr ""
+"Siga estos pasos para configurar\n"
+"Ultimaker Cura. Solo le llevará unos minutos."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:58
+msgctxt "@button"
+msgid "Get started"
+msgstr "Empezar"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:27
+msgctxt "@info:tooltip"
+msgid "3D View"
+msgstr "Vista en 3D"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:40
+msgctxt "@info:tooltip"
+msgid "Front View"
+msgstr "Vista frontal"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
+msgctxt "@info:tooltip"
+msgid "Top View"
+msgstr "Vista superior"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
+msgctxt "@info:tooltip"
+msgid "Left View"
+msgstr "Vista del lado izquierdo"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:79
+msgctxt "@info:tooltip"
+msgid "Right View"
+msgstr "Vista del lado derecho"
+
+#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
-msgstr "Permite guardar el segmento resultante como un archivo X3G para dar compatibilidad a impresoras que leen este formato (Malyan, Makerbot y otras impresoras basadas en Sailfish)."
+msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
+msgstr "Permite cambiar los ajustes de la máquina (como el volumen de impresión, el tamaño de la tobera, etc.)."
-#: X3GWriter/plugin.json
+#: MachineSettingsAction/plugin.json
msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3GWriter"
+msgid "Machine Settings action"
+msgstr "Acción Ajustes de la máquina"
+
+#: Toolbox/plugin.json
+msgctxt "description"
+msgid "Find, manage and install new Cura packages."
+msgstr "Buscar, administrar e instalar nuevos paquetes de Cura."
+
+#: Toolbox/plugin.json
+msgctxt "name"
+msgid "Toolbox"
+msgstr "Cuadro de herramientas"
+
+#: XRayView/plugin.json
+msgctxt "description"
+msgid "Provides the X-Ray view."
+msgstr "Proporciona la vista de rayos X."
+
+#: XRayView/plugin.json
+msgctxt "name"
+msgid "X-Ray View"
+msgstr "Vista de rayos X"
+
+#: X3DReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading X3D files."
+msgstr "Proporciona asistencia para leer archivos X3D."
+
+#: X3DReader/plugin.json
+msgctxt "name"
+msgid "X3D Reader"
+msgstr "Lector de X3D"
+
+#: GCodeWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a file."
+msgstr "Escribe GCode en un archivo."
+
+#: GCodeWriter/plugin.json
+msgctxt "name"
+msgid "G-code Writer"
+msgstr "Escritor de GCode"
+
+#: ModelChecker/plugin.json
+msgctxt "description"
+msgid "Checks models and print configuration for possible printing issues and give suggestions."
+msgstr "Comprueba las configuraciones de los modelos y la impresión en busca de posibles problemas de impresión y da consejos."
+
+#: ModelChecker/plugin.json
+msgctxt "name"
+msgid "Model Checker"
+msgstr "Comprobador de modelos"
+
+#: FirmwareUpdater/plugin.json
+msgctxt "description"
+msgid "Provides a machine actions for updating firmware."
+msgstr "Proporciona opciones a la máquina para actualizar el firmware."
+
+#: FirmwareUpdater/plugin.json
+msgctxt "name"
+msgid "Firmware Updater"
+msgstr "Actualizador de firmware"
+
+#: AMFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading AMF files."
+msgstr "Proporciona asistencia para leer archivos AMF."
+
+#: AMFReader/plugin.json
+msgctxt "name"
+msgid "AMF Reader"
+msgstr "Lector de AMF"
+
+#: USBPrinting/plugin.json
+msgctxt "description"
+msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
+msgstr "Acepta GCode y lo envía a una impresora. El complemento también puede actualizar el firmware."
+
+#: USBPrinting/plugin.json
+msgctxt "name"
+msgid "USB printing"
+msgstr "Impresión USB"
+
+#: GCodeGzWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a compressed archive."
+msgstr "Escribe GCode en un archivo comprimido."
+
+#: GCodeGzWriter/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Writer"
+msgstr "Escritor de GCode comprimido"
+
+#: UFPWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing Ultimaker Format Packages."
+msgstr "Permite la escritura de paquetes de formato Ultimaker."
+
+#: UFPWriter/plugin.json
+msgctxt "name"
+msgid "UFP Writer"
+msgstr "Escritor de UFP"
+
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Proporciona una fase de preparación en Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Fase de preparación"
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "description"
+msgid "Provides removable drive hotplugging and writing support."
+msgstr "Proporciona asistencia para la conexión directa y la escritura de la unidad extraíble."
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "name"
+msgid "Removable Drive Output Device Plugin"
+msgstr "Complemento de dispositivo de salida de unidad extraíble"
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "description"
+msgid "Manages network connections to Ultimaker networked printers."
+msgstr "Gestiona las conexiones de red de las impresoras Ultimaker conectadas."
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "name"
+msgid "Ultimaker Network Connection"
+msgstr "Conexión en red de Ultimaker"
+
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Proporciona una fase de supervisión en Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Fase de supervisión"
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "description"
+msgid "Checks for firmware updates."
+msgstr "Busca actualizaciones de firmware."
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "name"
+msgid "Firmware Update Checker"
+msgstr "Buscador de actualizaciones de firmware"
+
+#: SimulationView/plugin.json
+msgctxt "description"
+msgid "Provides the Simulation view."
+msgstr "Abre la vista de simulación."
+
+#: SimulationView/plugin.json
+msgctxt "name"
+msgid "Simulation View"
+msgstr "Vista de simulación"
+
+#: GCodeGzReader/plugin.json
+msgctxt "description"
+msgid "Reads g-code from a compressed archive."
+msgstr "Lee GCode de un archivo comprimido."
+
+#: GCodeGzReader/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Reader"
+msgstr "Lector de GCode comprimido"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "description"
+msgid "Extension that allows for user created scripts for post processing"
+msgstr "Extensión que permite el posprocesamiento de las secuencias de comandos creadas por los usuarios"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "name"
+msgid "Post Processing"
+msgstr "Posprocesamiento"
+
+#: SupportEraser/plugin.json
+msgctxt "description"
+msgid "Creates an eraser mesh to block the printing of support in certain places"
+msgstr "Crea una malla de borrado que impide la impresión de soportes en determinados lugares"
+
+#: SupportEraser/plugin.json
+msgctxt "name"
+msgid "Support Eraser"
+msgstr "Borrador de soporte"
+
+#: UFPReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading Ultimaker Format Packages."
+msgstr "Proporciona soporte para la lectura de paquetes de formato Ultimaker."
+
+#: UFPReader/plugin.json
+msgctxt "name"
+msgid "UFP Reader"
+msgstr "Lector de UFP"
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "description"
+msgid "Submits anonymous slice info. Can be disabled through preferences."
+msgstr "Envía información anónima de la segmentación. Se puede desactivar en las preferencias."
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "name"
+msgid "Slice info"
+msgstr "Info de la segmentación"
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "description"
+msgid "Provides capabilities to read and write XML-based material profiles."
+msgstr "Permite leer y escribir perfiles de material basados en XML."
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "name"
+msgid "Material Profiles"
+msgstr "Perfiles de material"
+
+#: LegacyProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from legacy Cura versions."
+msgstr "Proporciona asistencia para la importación de perfiles de versiones anteriores de Cura."
+
+#: LegacyProfileReader/plugin.json
+msgctxt "name"
+msgid "Legacy Cura Profile Reader"
+msgstr "Lector de perfiles antiguos de Cura"
+
+#: GCodeProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from g-code files."
+msgstr "Proporciona asistencia para la importación de perfiles de archivos GCode."
+
+#: GCodeProfileReader/plugin.json
+msgctxt "name"
+msgid "G-code Profile Reader"
+msgstr "Lector de perfiles GCode"
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
+msgstr "Actualiza la configuración de Cura 3.2 a Cura 3.3."
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.2 to 3.3"
+msgstr "Actualización de la versión 3.2 a la 3.3"
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
+msgstr "Actualiza la configuración de Cura 3.3 a Cura 3.4."
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.3 to 3.4"
+msgstr "Actualización de la versión 3.3 a la 3.4"
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.3 to Cura 4.4."
+msgstr "Actualiza la configuración de Cura 4.3 a Cura 4.4."
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.3 to 4.4"
+msgstr "Actualización de la versión 4.3 a la 4.4"
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
+msgstr "Actualiza la configuración de Cura 2.5 a Cura 2.6."
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.5 to 2.6"
+msgstr "Actualización de la versión 2.5 a la 2.6"
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
+msgstr "Actualiza la configuración de Cura 2.7 a Cura 3.0."
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.7 to 3.0"
+msgstr "Actualización de la versión 2.7 a la 3.0"
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.5 to Cura 4.0."
+msgstr "Actualiza la configuración de Cura 3.5 a Cura 4.0."
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.5 to 4.0"
+msgstr "Actualización de la versión 3.5 a la 4.0"
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
+msgstr "Actualiza las configuraciones de Cura 3.4 a Cura 3.5."
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.4 to 3.5"
+msgstr "Actualización de la versión 3.4 a la 3.5"
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.0 to Cura 4.1."
+msgstr "Actualiza la configuración de Cura 4.0 a Cura 4.1."
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.0 to 4.1"
+msgstr "Actualización de la versión 4.0 a la 4.1"
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
+msgstr "Actualiza la configuración de Cura 3.0 a Cura 3.1."
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.0 to 3.1"
+msgstr "Actualización de la versión 3.0 a la 3.1"
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.1 to Cura 4.2."
+msgstr "Actualiza la configuración de Cura 4.1 a Cura 4.2."
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.1 to 4.2"
+msgstr "Actualización de la versión 4.1 a la 4.2"
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
+msgstr "Actualiza la configuración de Cura 2.6 a Cura 2.7."
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.6 to 2.7"
+msgstr "Actualización de la versión 2.6 a la 2.7"
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
+msgstr "Actualiza las configuraciones de Cura 2.1 a Cura 2.2."
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.1 to 2.2"
+msgstr "Actualización de la versión 2.1 a la 2.2"
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
+msgstr "Actualiza la configuración de Cura 2.2 a Cura 2.4."
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.2 to 2.4"
+msgstr "Actualización de la versión 2.2 a la 2.4"
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.2 to Cura 4.3."
+msgstr "Actualiza la configuración de Cura 4.2 a Cura 4.3."
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.2 to 4.3"
+msgstr "Actualización de la versión 4.2 a la 4.3"
+
+#: ImageReader/plugin.json
+msgctxt "description"
+msgid "Enables ability to generate printable geometry from 2D image files."
+msgstr "Habilita la capacidad de generar geometría imprimible a partir de archivos de imagen 2D."
+
+#: ImageReader/plugin.json
+msgctxt "name"
+msgid "Image Reader"
+msgstr "Lector de imágenes"
+
+#: TrimeshReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading model files."
+msgstr "Proporciona asistencia para leer archivos 3D."
+
+#: TrimeshReader/plugin.json
+msgctxt "name"
+msgid "Trimesh Reader"
+msgstr "Lector Trimesh"
+
+#: CuraEngineBackend/plugin.json
+msgctxt "description"
+msgid "Provides the link to the CuraEngine slicing backend."
+msgstr "Proporciona el vínculo para el backend de segmentación de CuraEngine."
+
+#: CuraEngineBackend/plugin.json
+msgctxt "name"
+msgid "CuraEngine Backend"
+msgstr "Backend de CuraEngine"
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "description"
+msgid "Provides the Per Model Settings."
+msgstr "Proporciona los ajustes por modelo."
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "name"
+msgid "Per Model Settings Tool"
+msgstr "Herramienta de ajustes por modelo"
+
+#: 3MFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading 3MF files."
+msgstr "Proporciona asistencia para leer archivos 3MF."
+
+#: 3MFReader/plugin.json
+msgctxt "name"
+msgid "3MF Reader"
+msgstr "Lector de 3MF"
+
+#: SolidView/plugin.json
+msgctxt "description"
+msgid "Provides a normal solid mesh view."
+msgstr "Proporciona una vista de malla sólida normal."
+
+#: SolidView/plugin.json
+msgctxt "name"
+msgid "Solid View"
+msgstr "Vista de sólidos"
+
+#: GCodeReader/plugin.json
+msgctxt "description"
+msgid "Allows loading and displaying G-code files."
+msgstr "Permite cargar y visualizar archivos GCode."
+
+#: GCodeReader/plugin.json
+msgctxt "name"
+msgid "G-code Reader"
+msgstr "Lector de GCode"
+
+#: CuraDrive/plugin.json
+msgctxt "description"
+msgid "Backup and restore your configuration."
+msgstr "Realice una copia de seguridad de su configuración y restáurela."
+
+#: CuraDrive/plugin.json
+msgctxt "name"
+msgid "Cura Backups"
+msgstr "Copias de seguridad de Cura"
+
+#: CuraProfileWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for exporting Cura profiles."
+msgstr "Proporciona asistencia para exportar perfiles de Cura."
+
+#: CuraProfileWriter/plugin.json
+msgctxt "name"
+msgid "Cura Profile Writer"
+msgstr "Escritor de perfiles de Cura"
+
+#: 3MFWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing 3MF files."
+msgstr "Proporciona asistencia para escribir archivos 3MF."
+
+#: 3MFWriter/plugin.json
+msgctxt "name"
+msgid "3MF Writer"
+msgstr "Escritor de 3MF"
+
+#: PreviewStage/plugin.json
+msgctxt "description"
+msgid "Provides a preview stage in Cura."
+msgstr "Proporciona una fase de vista previa en Cura."
+
+#: PreviewStage/plugin.json
+msgctxt "name"
+msgid "Preview Stage"
+msgstr "Fase de vista previa"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "description"
+msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
+msgstr "Proporciona las acciones de la máquina de las máquinas Ultimaker (como un asistente para la nivelación de la plataforma, la selección de actualizaciones, etc.)."
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "name"
+msgid "Ultimaker machine actions"
+msgstr "Acciones de la máquina Ultimaker"
+
+#: CuraProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing Cura profiles."
+msgstr "Proporciona asistencia para la importación de perfiles de Cura."
+
+#: CuraProfileReader/plugin.json
+msgctxt "name"
+msgid "Cura Profile Reader"
+msgstr "Lector de perfiles de Cura"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Flatten active settings"
+#~ msgstr "Aplanar ajustes activos"
+
+#~ msgctxt "@info:status"
+#~ msgid "Profile has been flattened & activated."
+#~ msgstr "El perfil se ha aplanado y activado."
+
+#~ msgctxt "X3g Writer Plugin Description"
+#~ msgid "Writes X3g to files"
+#~ msgstr "Escribe X3g en archivos"
+
+#~ msgctxt "X3g Writer File Description"
+#~ msgid "X3g File"
+#~ msgstr "Archivo X3g"
+
+#~ msgctxt "X3G Writer File Description"
+#~ msgid "X3G File"
+#~ msgstr "Archivo X3G"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Open Compressed Triangle Mesh"
+#~ msgstr ""
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Profile Assistant"
+#~ msgstr "Asistente del perfil"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Profile Assistant"
+#~ msgstr "Asistente del perfil"
+
+#~ msgctxt "@action:button"
+#~ msgid "Retry"
+#~ msgstr "Volver a intentar"
+
+#~ msgctxt "@label:table_header"
+#~ msgid "Print Core"
+#~ msgstr "Print core"
+
+#~ msgctxt "@label"
+#~ msgid "Don't support overlap with other models"
+#~ msgstr "No crear soporte en otros modelos (por superposición)"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for overlap with other models"
+#~ msgstr "Modificar ajustes de otros modelos (por superposición)"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for infill of other models"
+#~ msgstr "Modificar ajustes del relleno de otros modelos"
+
+#~ msgctxt "@action:ComboBox option"
+#~ msgid "Update existing"
+#~ msgstr "Actualizar existente"
+
+#~ msgctxt "@label"
+#~ msgid "Not supported"
+#~ msgstr "No compatible"
+
+#~ msgctxt "@action:button"
+#~ msgid "Previous"
+#~ msgstr "Anterior"
+
+#~ msgctxt "@label"
+#~ msgid "Tip"
+#~ msgstr "Consejo"
+
+#~ msgctxt "@label"
+#~ msgid "Print experiment"
+#~ msgstr "Ensayo de impresión"
+
+#~ msgctxt "@label"
+#~ msgid "Checklist"
+#~ msgstr "Lista de verificación"
+
+#~ msgctxt "@label"
+#~ msgid "Please select any upgrades made to this Ultimaker 2."
+#~ msgstr "Seleccione cualquier actualización de este Ultimaker 2."
+
+#~ msgctxt "@label"
+#~ msgid "Olsson Block"
+#~ msgstr "Bloque Olsson"
+
+#~ msgctxt "@window:text"
+#~ msgid "Camera rendering: "
+#~ msgstr "Renderizado de cámara: "
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Use multi build plate functionality"
+#~ msgstr "Utilizar funcionalidad de placa de impresión múltiple"
+
+#~ msgctxt "@option:check"
+#~ msgid "Use multi build plate functionality (restart required)"
+#~ msgstr "Utilizar funcionalidad de placa de impresión múltiple (reinicio requerido)"
+
+#~ msgctxt "@label"
+#~ msgid "Default profiles"
+#~ msgstr "Perfiles predeterminados"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "search settings"
+#~ msgstr "buscar ajustes"
+
+#~ msgctxt "@label"
+#~ msgid "Layer Height"
+#~ msgstr "Altura de capa"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile."
+#~ msgstr "Este perfil de calidad no se encuentra disponible para su configuración de material y tobera actual. Cámbielas para poder habilitar este perfil de calidad."
+
+#~ msgctxt "@tooltip"
+#~ msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
+#~ msgstr "Hay un perfil personalizado activado en este momento. Para habilitar el control deslizante de calidad, seleccione un perfil de calidad predeterminado en la pestaña Personalizado"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Build plate"
+#~ msgstr "&Placa de impresión"
+
+#~ msgctxt "@title:settings"
+#~ msgid "&Profile"
+#~ msgstr "&Perfil"
+
+#~ msgctxt "@action:label"
+#~ msgid "Build plate"
+#~ msgstr "Placa de impresión"
+
+#~ msgctxt "description"
+#~ msgid "Dump the contents of all settings to a HTML file."
+#~ msgstr "Vuelva el contenido de todas las configuraciones en un archivo HTML."
+
+#~ msgctxt "name"
+#~ msgid "God Mode"
+#~ msgstr "God Mode"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattened quality changes profile."
+#~ msgstr "Crear un perfil de cambios de calidad aplanado."
+
+#~ msgctxt "name"
+#~ msgid "Profile Flattener"
+#~ msgstr "Aplanador de perfil"
+
+#~ msgctxt "description"
+#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+#~ msgstr "Permite a los fabricantes de material crear nuevos perfiles de material y calidad mediante una IU integrada."
+
+#~ msgctxt "name"
+#~ msgid "Print Profile Assistant"
+#~ msgstr "Imprimir asistente del perfil"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network."
+#~ msgstr "Conectado a través de la red."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. Please approve the access request on the printer."
+#~ msgstr "Conectado a través de la red. Apruebe la solicitud de acceso en la impresora."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. No access to control the printer."
+#~ msgstr "Conectado a través de la red. No hay acceso para controlar la impresora."
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer requested. Please approve the request on the printer"
+#~ msgstr "Acceso a la impresora solicitado. Apruebe la solicitud en la impresora"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication status"
+#~ msgstr "Estado de la autenticación"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication Status"
+#~ msgstr "Estado de la autenticación"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Re-send the access request"
+#~ msgstr "Reenvía la solicitud de acceso"
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer accepted"
+#~ msgstr "Acceso a la impresora aceptado"
+
+#~ msgctxt "@info:status"
+#~ msgid "No access to print with this printer. Unable to send print job."
+#~ msgstr "No hay acceso para imprimir con esta impresora. No se puede enviar el trabajo de impresión."
+
+#~ msgctxt "@action:button"
+#~ msgid "Request Access"
+#~ msgstr "Solicitar acceso"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Send access request to the printer"
+#~ msgstr "Envía la solicitud de acceso a la impresora"
+
+#~ msgctxt "@label"
+#~ msgid "Unable to start a new print job."
+#~ msgstr "No se puede iniciar un nuevo trabajo de impresión."
+
+#~ msgctxt "@label"
+#~ msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
+#~ msgstr "Un problema con la configuración de Ultimaker impide iniciar la impresión. Soluciónelo antes de continuar."
+
+#~ msgctxt "@window:title"
+#~ msgid "Mismatched configuration"
+#~ msgstr "Configuración desajustada"
+
+#~ msgctxt "@label"
+#~ msgid "Are you sure you wish to print with the selected configuration?"
+#~ msgstr "¿Seguro que desea imprimir con la configuración seleccionada?"
+
+#~ msgctxt "@label"
+#~ msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "La configuración o calibración de la impresora y de Cura no coinciden. Para obtener el mejor resultado, segmente siempre los PrintCores y los materiales que se insertan en la impresora."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
+#~ msgstr "Envío de nuevos trabajos (temporalmente) bloqueado; se sigue enviando el trabajo de impresión previo."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to printer"
+#~ msgstr "Enviando datos a la impresora"
+
+#~ msgctxt "@info:title"
+#~ msgid "Sending Data"
+#~ msgstr "Enviando datos"
+
+#~ msgctxt "@info:status"
+#~ msgid "No Printcore loaded in slot {slot_number}"
+#~ msgstr "No se ha cargado ningún PrintCore en la ranura {slot_number}."
+
+#~ msgctxt "@info:status"
+#~ msgid "No material loaded in slot {slot_number}"
+#~ msgstr "No se ha cargado ningún material en la ranura {slot_number}."
+
+#~ msgctxt "@label"
+#~ msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
+#~ msgstr "PrintCore distinto (Cura: {cura_printcore_name}, impresora: {remote_printcore_name}) seleccionado para extrusor {extruder_id}"
+
+#~ msgctxt "@label"
+#~ msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
+#~ msgstr "Material distinto (Cura: {0}, impresora: {1}) seleccionado para extrusor {2}"
+
+#~ msgctxt "@window:title"
+#~ msgid "Sync with your printer"
+#~ msgstr "Sincronizar con la impresora"
+
+#~ msgctxt "@label"
+#~ msgid "Would you like to use your current printer configuration in Cura?"
+#~ msgstr "¿Desea utilizar la configuración actual de su impresora en Cura?"
+
+#~ msgctxt "@label"
+#~ msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Los PrintCores o los materiales de la impresora difieren de los del proyecto actual. Para obtener el mejor resultado, segmente siempre los PrintCores y materiales que se hayan insertado en la impresora."
+
+#~ msgctxt "@action:button"
+#~ msgid "View in Monitor"
+#~ msgstr "Ver en pantalla"
+
+#~ msgctxt "@info:status"
+#~ msgid "Printer '{printer_name}' has finished printing '{job_name}'."
+#~ msgstr "{printer_name} ha terminado de imprimir «{job_name}»."
+
+#~ msgctxt "@info:status"
+#~ msgid "The print job '{job_name}' was finished."
+#~ msgstr "El trabajo de impresión '{job_name}' ha terminado."
+
+#~ msgctxt "@info:status"
+#~ msgid "Print finished"
+#~ msgstr "Impresión terminada"
+
+#~ msgctxt "@label:material"
+#~ msgid "Empty"
+#~ msgstr "Vacío"
+
+#~ msgctxt "@label:material"
+#~ msgid "Unknown"
+#~ msgstr "Desconocido"
+
+#~ msgctxt "@info:title"
+#~ msgid "Cloud error"
+#~ msgstr "Error de Cloud"
+
+#~ msgctxt "@info:status"
+#~ msgid "Could not export print job."
+#~ msgstr "No se ha podido exportar el trabajo de impresión."
+
+#~ msgctxt "@info:description"
+#~ msgid "There was an error connecting to the cloud."
+#~ msgstr "Se ha producido un error al conectarse a la nube."
+
+#~ msgctxt "@info:status"
+#~ msgid "Uploading via Ultimaker Cloud"
+#~ msgstr "Cargando a través de Ultimaker Cloud"
+
+#~ msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Conectar a Ultimaker Cloud"
+
+#~ msgctxt "@action"
+#~ msgid "Don't ask me again for this printer."
+#~ msgstr "No volver a preguntarme para esta impresora."
+
+#~ msgctxt "@info:status"
+#~ msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
+#~ msgstr "Ahora ya puede enviar y supervisar sus trabajos de impresión desde cualquier lugar a través de su cuenta de Ultimaker."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected!"
+#~ msgstr "¡Conectado!"
+
+#~ msgctxt "@action"
+#~ msgid "Review your connection"
+#~ msgstr "Revise su conexión"
+
+#~ msgctxt "@info:status Don't translate the XML tags !"
+#~ msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
+#~ msgstr "El equipo definido en el perfil {0} ({1}) no coincide con el equipo actual ({2}), no se ha podido importar."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}:"
+#~ msgstr "Error al importar el perfil de {0}:"
+
+#~ msgctxt "@window:title"
+#~ msgid "Existing Connection"
+#~ msgstr "Conexión existente"
+
+#~ msgctxt "@message:text"
+#~ msgid "This printer/group is already added to Cura. Please select another printer/group."
+#~ msgstr "Esta impresora o grupo de impresoras ya se ha añadido a Cura. Seleccione otra impresora o grupo de impresoras."
+
+#~ msgctxt "@label"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Introduzca la dirección IP o el nombre de host de la impresora en la red."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Connect to a printer"
+#~ msgstr "Conecta a una impresora"
+
+#~ msgctxt "@title"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Guía de ajustes de Cura"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Zooming towards the mouse is not supported in the orthogonal perspective."
+#~ msgstr "Hacer zoom en la dirección del ratón no es compatible con la perspectiva ortogonal."
+
+#~ msgid "Orthogonal"
+#~ msgstr "Ortográfica"
+
+#~ msgctxt "description"
+#~ msgid "Manages network connections to Ultimaker 3 printers."
+#~ msgstr "Gestiona las conexiones de red a las impresoras Ultimaker 3."
+
+#~ msgctxt "name"
+#~ msgid "UM3 Network Connection"
+#~ msgstr "Conexión de red UM3"
+
+#~ msgctxt "description"
+#~ msgid "Provides extra information and explanations about settings in Cura, with images and animations."
+#~ msgstr "Proporciona información y explicaciones adicionales sobre los ajustes de Cura con imágenes y animaciones."
+
+#~ msgctxt "name"
+#~ msgid "Settings Guide"
+#~ msgstr "Guía de ajustes"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Guía de ajustes de Cura"
+
+#~ msgctxt "@info:generic"
+#~ msgid "Settings have been changed to match the current availability of extruders: [%s]"
+#~ msgstr "La configuración se ha cambiado para que coincida con los extrusores disponibles en este momento: [%s]."
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "User description"
+#~ msgstr "Descripción del usuario"
+
+#~ msgctxt "@info"
+#~ msgid "These options are not available because you are monitoring a cloud printer."
+#~ msgstr "Estas opciones no se encuentran disponibles porque está supervisando una impresora en la nube."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Go to Cura Connect"
+#~ msgstr "Ir a Cura Connect"
+
+#~ msgctxt "@info"
+#~ msgid "All jobs are printed."
+#~ msgstr "Se han imprimido todos los trabajos."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "View print history"
+#~ msgstr "Ver historial de impresión"
+
+#~ msgctxt "@label"
+#~ msgid ""
+#~ "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
+#~ "\n"
+#~ "Select your printer from the list below:"
+#~ msgstr ""
+#~ "Para imprimir directamente en la impresora a través de la red, asegúrese de que ésta está conectada a la red utilizando un cable de red o conéctela a la red wifi. Si no conecta Cura con la impresora, también puede utilizar una unidad USB para transferir archivos GCode a la impresora.\n"
+#~ "\n"
+#~ "Seleccione la impresora de la siguiente lista:"
+
+#~ msgctxt "@info"
+#~ msgid ""
+#~ "Please make sure your printer has a connection:\n"
+#~ "- Check if the printer is turned on.\n"
+#~ "- Check if the printer is connected to the network."
+#~ msgstr ""
+#~ "Asegúrese de que su impresora está conectada:\n"
+#~ "- Compruebe que la impresora está encendida.\n"
+#~ "- Compruebe que la impresora está conectada a la red."
+
+#~ msgctxt "@option:check"
+#~ msgid "See only current build plate"
+#~ msgstr "Ver solo placa de impresión actual"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange to all build plates"
+#~ msgstr "Organizar todas las placas de impresión"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange current build plate"
+#~ msgstr "Organizar placa de impresión actual"
+
+#~ msgctxt "description"
+#~ msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
+#~ msgstr "Permite guardar el segmento resultante como un archivo X3G para dar compatibilidad a impresoras que leen este formato (Malyan, Makerbot y otras impresoras basadas en Sailfish)."
+
+#~ msgctxt "name"
+#~ msgid "X3GWriter"
+#~ msgstr "X3GWriter"
+
+#~ msgctxt "description"
+#~ msgid "Reads SVG files as toolpaths, for debugging printer movements."
+#~ msgstr "Lee archivos SVG como trayectorias de herramienta para solucionar errores en los movimientos de la impresora."
+
+#~ msgctxt "name"
+#~ msgid "SVG Toolpath Reader"
+#~ msgstr "Lector de trayectoria de herramienta de SVG"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Changelog"
+#~ msgstr "Registro de cambios"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Show Changelog"
+#~ msgstr "Mostrar registro de cambios"
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to remote cluster"
+#~ msgstr "Enviando datos al clúster remoto"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Conectar a Ultimaker Cloud"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymized usage statistics."
+#~ msgstr "Cura recopila estadísticas de uso de forma anónima."
+
+#~ msgctxt "@info:title"
+#~ msgid "Collecting Data"
+#~ msgstr "Recopilando datos"
+
+#~ msgctxt "@action:button"
+#~ msgid "More info"
+#~ msgstr "Más información"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "See more information on what data Cura sends."
+#~ msgstr "Obtenga más información sobre qué datos envía Cura."
+
+#~ msgctxt "@action:button"
+#~ msgid "Allow"
+#~ msgstr "Permitir"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
+#~ msgstr "Permitir a Cura enviar estadísticas de uso de forma anónima para ayudar a priorizar mejoras futuras para Cura. Se envían algunas de sus preferencias y ajustes, la versión de Cura y un resumen de los modelos que está fragmentando."
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Evaluation"
+#~ msgstr "Evaluación"
+
+#~ msgctxt "@info:title"
+#~ msgid "Network enabled printers"
+#~ msgstr "Impresoras de red habilitadas"
+
+#~ msgctxt "@info:title"
+#~ msgid "Local printers"
+#~ msgstr "Impresoras locales"
+
+#~ msgctxt "@info:backup_failed"
+#~ msgid "Tried to restore a Cura backup that does not match your current version."
+#~ msgstr "Se ha intentado restaurar una copia de seguridad de Cura que no coincide con la versión actual."
+
+#~ msgctxt "@title"
+#~ msgid "Machine Settings"
+#~ msgstr "Ajustes de la máquina"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Settings"
+#~ msgstr "Ajustes de la impresora"
+
+#~ msgctxt "@option:check"
+#~ msgid "Origin at center"
+#~ msgstr "Origen en el centro"
+
+#~ msgctxt "@option:check"
+#~ msgid "Heated bed"
+#~ msgstr "Plataforma caliente"
+
+#~ msgctxt "@label"
+#~ msgid "Printhead Settings"
+#~ msgstr "Ajustes del cabezal de impresión"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distancia desde la parte izquierda del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distancia desde la parte frontal del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distancia desde la parte derecha del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distancia desde la parte trasera del cabezal de impresión hasta el centro de la tobera. Se usa para evitar que colisionen la impresión anterior con el cabezal de impresión al imprimir «de uno en uno»."
+
+#~ msgctxt "@label"
+#~ msgid "Gantry height"
+#~ msgstr "Altura del caballete"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
+#~ msgstr "Diferencia de altura entre la punta de la tobera y el sistema del puente (ejes X e Y). Se usa para evitar que colisionen la impresión anterior con el caballete al imprimir «de uno en uno»."
+
+#~ msgctxt "@label"
+#~ msgid "Start G-code"
+#~ msgstr "Iniciar GCode"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very start."
+#~ msgstr "Los comandos de GCode que se ejecutarán justo al inicio."
+
+#~ msgctxt "@label"
+#~ msgid "End G-code"
+#~ msgstr "Finalizar GCode"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very end."
+#~ msgstr "Los comandos de GCode que se ejecutarán justo al final."
+
+#~ msgctxt "@label"
+#~ msgid "Nozzle Settings"
+#~ msgstr "Ajustes de la tobera"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
+#~ msgstr "El diámetro nominal del filamento compatible con la impresora. El diámetro exacto se sobrescribirá según el material o el perfil."
+
+#~ msgctxt "@label"
+#~ msgid "Extruder Start G-code"
+#~ msgstr "GCode inicial del extrusor"
+
+#~ msgctxt "@label"
+#~ msgid "Extruder End G-code"
+#~ msgstr "GCode final del extrusor"
+
+#~ msgctxt "@label"
+#~ msgid "Changelog"
+#~ msgstr "Registro de cambios"
+
+#~ msgctxt "@title:window"
+#~ msgid "User Agreement"
+#~ msgstr "Acuerdo de usuario"
+
+#~ msgctxt "@alabel"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Introduzca la dirección IP o el nombre de host de la impresora en red."
+
+#~ msgctxt "@info"
+#~ msgid "Please select a network connected printer to monitor."
+#~ msgstr "Seleccione la impresora conectada a la red que desee supervisar."
+
+#~ msgctxt "@info"
+#~ msgid "Please connect your Ultimaker printer to your local network."
+#~ msgstr "Conecte su impresora Ultimaker a su red local."
+
+#~ msgctxt "@text:window"
+#~ msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
+#~ msgstr "Cura envía datos anónimos a Ultimaker para mejorar la calidad de impresión y la experiencia de usuario. A continuación, hay un ejemplo de todos los datos que se han enviado."
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send this data"
+#~ msgstr "No deseo enviar estos datos"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending this data to Ultimaker and help us improve Cura"
+#~ msgstr "Permita que estos datos se envíen a Ultimaker y ayúdenos a mejorar Cura"
+
+#~ msgctxt "@label"
+#~ msgid "No print selected"
+#~ msgstr "No ha seleccionado ninguna impresora"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
+#~ msgstr "De manera predeterminada, los píxeles blancos representan los puntos altos de la malla y los píxeles negros representan los puntos bajos de la malla. Cambie esta opción para invertir el comportamiento de tal manera que los píxeles negros representen los puntos altos de la malla y los píxeles blancos representen los puntos bajos de la malla."
+
+#~ msgctxt "@title"
+#~ msgid "Select Printer Upgrades"
+#~ msgstr "Seleccionar actualizaciones de impresora"
+
+#~ msgctxt "@label"
+#~ msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
+#~ msgstr "Seleccione qué extrusor se utilizará como soporte. Esta opción formará estructuras de soporte por debajo del modelo para evitar que éste se combe o la impresión se haga en el aire."
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
+#~ msgstr "Este perfil de calidad no se encuentra disponible para su configuración de material y tobera actual. Cámbiela para poder habilitar este perfil de calidad."
+
+#~ msgctxt "@label shown when we load a Gcode file"
+#~ msgid "Print setup disabled. G code file can not be modified."
+#~ msgstr "Configuración de impresión deshabilitada. No se puede modificar el GCode."
+
+#~ msgctxt "@label"
+#~ msgid "See the material compatibility chart"
+#~ msgstr "Ver el gráfico de compatibilidad de materiales"
+
+#~ msgctxt "@label"
+#~ msgid "View types"
+#~ msgstr "Ver tipos"
+
+#~ msgctxt "@label"
+#~ msgid "Hi "
+#~ msgstr "Hola "
+
+#~ msgctxt "@text"
+#~ msgid ""
+#~ "- Send print jobs to Ultimaker printers outside your local network\n"
+#~ "- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
+#~ "- Get exclusive access to material profiles from leading brands"
+#~ msgstr ""
+#~ "- Envíe trabajos de impresión a impresoras Ultimaker fuera de su red local\n"
+#~ "- Guarde su configuración de Ultimaker Cura en la nube para poder usarla en cualquier lugar\n"
+#~ "- Disfrute de acceso exclusivo a perfiles de materiales de marcas líderes"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Unable to Slice"
+#~ msgstr "No se puede segmentar"
+
+#~ msgctxt "@label"
+#~ msgid "Time specification"
+#~ msgstr "Especificación de tiempos"
+
+#~ msgctxt "@label"
+#~ msgid "Material specification"
+#~ msgstr "Especificación de materiales"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Add a printer to Cura"
+#~ msgstr "Añadir una impresora a Cura"
+
+#~ msgctxt "@title:tab"
+#~ msgid ""
+#~ "Select the printer you want to use from the list below.\n"
+#~ "\n"
+#~ "If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
+#~ msgstr ""
+#~ "Seleccione la impresora que desee utilizar de la lista que se muestra a continuación.\n"
+#~ "\n"
+#~ "Si no encuentra su impresora en la lista, utilice la opción \"Custom FFF Printer\" (Impresora FFF personalizada) de la categoría Personalizado y configure los ajustes para adaptarlos a su impresora en el siguiente cuadro de diálogo."
+
+#~ msgctxt "@label"
+#~ msgid "Manufacturer"
+#~ msgstr "Fabricante"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name"
+#~ msgstr "Nombre de la impresora"
+
+#~ msgctxt "@action:button"
+#~ msgid "Add Printer"
+#~ msgstr "Agregar impresora"
#~ msgid "Modify G-Code"
#~ msgstr "Modificar GCode"
@@ -5328,62 +6476,6 @@ msgstr "X3GWriter"
#~ msgid "Click to check the material compatibility on Ultimaker.com."
#~ msgstr "Haga clic para comprobar la compatibilidad de los materiales en Utimaker.com."
-#~ msgctxt "description"
-#~ msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
-#~ msgstr "Permite cambiar los ajustes de la máquina (como el volumen de impresión, el tamaño de la tobera, etc.)."
-
-#~ msgctxt "name"
-#~ msgid "Machine Settings action"
-#~ msgstr "Acción Ajustes de la máquina"
-
-#~ msgctxt "description"
-#~ msgid "Find, manage and install new Cura packages."
-#~ msgstr "Buscar, administrar e instalar nuevos paquetes de Cura."
-
-#~ msgctxt "name"
-#~ msgid "Toolbox"
-#~ msgstr "Cuadro de herramientas"
-
-#~ msgctxt "description"
-#~ msgid "Provides the X-Ray view."
-#~ msgstr "Proporciona la vista de rayos X."
-
-#~ msgctxt "name"
-#~ msgid "X-Ray View"
-#~ msgstr "Vista de rayos X"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading X3D files."
-#~ msgstr "Proporciona asistencia para leer archivos X3D."
-
-#~ msgctxt "name"
-#~ msgid "X3D Reader"
-#~ msgstr "Lector de X3D"
-
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a file."
-#~ msgstr "Escribe GCode en un archivo."
-
-#~ msgctxt "name"
-#~ msgid "G-code Writer"
-#~ msgstr "Escritor de GCode"
-
-#~ msgctxt "description"
-#~ msgid "Checks models and print configuration for possible printing issues and give suggestions."
-#~ msgstr "Comprueba las configuraciones de los modelos y la impresión en busca de posibles problemas de impresión y da consejos."
-
-#~ msgctxt "name"
-#~ msgid "Model Checker"
-#~ msgstr "Comprobador de modelos"
-
-#~ msgctxt "description"
-#~ msgid "Dump the contents of all settings to a HTML file."
-#~ msgstr "Vuelva el contenido de todas las configuraciones en un archivo HTML."
-
-#~ msgctxt "name"
-#~ msgid "God Mode"
-#~ msgstr "God Mode"
-
#~ msgctxt "description"
#~ msgid "Shows changes since latest checked version."
#~ msgstr "Muestra los cambios desde la última versión comprobada."
@@ -5392,14 +6484,6 @@ msgstr "X3GWriter"
#~ msgid "Changelog"
#~ msgstr "Registro de cambios"
-#~ msgctxt "description"
-#~ msgid "Provides a machine actions for updating firmware."
-#~ msgstr "Proporciona opciones a la máquina para actualizar el firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Updater"
-#~ msgstr "Actualizador de firmware"
-
#~ msgctxt "description"
#~ msgid "Create a flattend quality changes profile."
#~ msgstr "Crear un perfil de cambios de calidad aplanado."
@@ -5408,14 +6492,6 @@ msgstr "X3GWriter"
#~ msgid "Profile flatener"
#~ msgstr "Aplanador de perfil"
-#~ msgctxt "description"
-#~ msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
-#~ msgstr "Acepta GCode y lo envía a una impresora. El complemento también puede actualizar el firmware."
-
-#~ msgctxt "name"
-#~ msgid "USB printing"
-#~ msgstr "Impresión USB"
-
#~ msgctxt "description"
#~ msgid "Ask the user once if he/she agrees with our license."
#~ msgstr "Preguntar al usuario una vez si acepta la licencia."
@@ -5424,278 +6500,6 @@ msgstr "X3GWriter"
#~ msgid "UserAgreement"
#~ msgstr "UserAgreement"
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a compressed archive."
-#~ msgstr "Escribe GCode en un archivo comprimido."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Writer"
-#~ msgstr "Escritor de GCode comprimido"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing Ultimaker Format Packages."
-#~ msgstr "Permite la escritura de paquetes de formato Ultimaker."
-
-#~ msgctxt "name"
-#~ msgid "UFP Writer"
-#~ msgstr "Escritor de UFP"
-
-#~ msgctxt "description"
-#~ msgid "Provides a prepare stage in Cura."
-#~ msgstr "Proporciona una fase de preparación en Cura."
-
-#~ msgctxt "name"
-#~ msgid "Prepare Stage"
-#~ msgstr "Fase de preparación"
-
-#~ msgctxt "description"
-#~ msgid "Provides removable drive hotplugging and writing support."
-#~ msgstr "Proporciona asistencia para la conexión directa y la escritura de la unidad extraíble."
-
-#~ msgctxt "name"
-#~ msgid "Removable Drive Output Device Plugin"
-#~ msgstr "Complemento de dispositivo de salida de unidad extraíble"
-
-#~ msgctxt "description"
-#~ msgid "Manages network connections to Ultimaker 3 printers."
-#~ msgstr "Gestiona las conexiones de red a las impresoras Ultimaker 3."
-
-#~ msgctxt "name"
-#~ msgid "UM3 Network Connection"
-#~ msgstr "Conexión de red UM3"
-
-#~ msgctxt "description"
-#~ msgid "Provides a monitor stage in Cura."
-#~ msgstr "Proporciona una fase de supervisión en Cura."
-
-#~ msgctxt "name"
-#~ msgid "Monitor Stage"
-#~ msgstr "Fase de supervisión"
-
-#~ msgctxt "description"
-#~ msgid "Checks for firmware updates."
-#~ msgstr "Busca actualizaciones de firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Update Checker"
-#~ msgstr "Buscador de actualizaciones de firmware"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Simulation view."
-#~ msgstr "Abre la vista de simulación."
-
-#~ msgctxt "name"
-#~ msgid "Simulation View"
-#~ msgstr "Vista de simulación"
-
-#~ msgctxt "description"
-#~ msgid "Reads g-code from a compressed archive."
-#~ msgstr "Lee GCode de un archivo comprimido."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Reader"
-#~ msgstr "Lector de GCode comprimido"
-
-#~ msgctxt "description"
-#~ msgid "Extension that allows for user created scripts for post processing"
-#~ msgstr "Extensión que permite el posprocesamiento de las secuencias de comandos creadas por los usuarios"
-
-#~ msgctxt "name"
-#~ msgid "Post Processing"
-#~ msgstr "Posprocesamiento"
-
-#~ msgctxt "description"
-#~ msgid "Creates an eraser mesh to block the printing of support in certain places"
-#~ msgstr "Crea una malla de borrado que impide la impresión de soportes en determinados lugares"
-
-#~ msgctxt "name"
-#~ msgid "Support Eraser"
-#~ msgstr "Borrador de soporte"
-
-#~ msgctxt "description"
-#~ msgid "Submits anonymous slice info. Can be disabled through preferences."
-#~ msgstr "Envía información anónima de la segmentación. Se puede desactivar en las preferencias."
-
-#~ msgctxt "name"
-#~ msgid "Slice info"
-#~ msgstr "Info de la segmentación"
-
-#~ msgctxt "description"
-#~ msgid "Provides capabilities to read and write XML-based material profiles."
-#~ msgstr "Permite leer y escribir perfiles de material basados en XML."
-
-#~ msgctxt "name"
-#~ msgid "Material Profiles"
-#~ msgstr "Perfiles de material"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from legacy Cura versions."
-#~ msgstr "Proporciona asistencia para la importación de perfiles de versiones anteriores de Cura."
-
-#~ msgctxt "name"
-#~ msgid "Legacy Cura Profile Reader"
-#~ msgstr "Lector de perfiles antiguos de Cura"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from g-code files."
-#~ msgstr "Proporciona asistencia para la importación de perfiles de archivos GCode."
-
-#~ msgctxt "name"
-#~ msgid "G-code Profile Reader"
-#~ msgstr "Lector de perfiles GCode"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
-#~ msgstr "Actualiza la configuración de Cura 3.2 a Cura 3.3."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.2 to 3.3"
-#~ msgstr "Actualización de la versión 3.2 a la 3.3"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
-#~ msgstr "Actualiza la configuración de Cura 3.3 a Cura 3.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.3 to 3.4"
-#~ msgstr "Actualización de la versión 3.3 a la 3.4"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
-#~ msgstr "Actualiza la configuración de Cura 2.5 a Cura 2.6."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.5 to 2.6"
-#~ msgstr "Actualización de la versión 2.5 a la 2.6"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
-#~ msgstr "Actualiza la configuración de Cura 2.7 a Cura 3.0."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.7 to 3.0"
-#~ msgstr "Actualización de la versión 2.7 a la 3.0"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
-#~ msgstr "Actualiza las configuraciones de Cura 3.4 a Cura 3.5."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.4 to 3.5"
-#~ msgstr "Actualización de la versión 3.4 a la 3.5"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
-#~ msgstr "Actualiza la configuración de Cura 3.0 a Cura 3.1."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.0 to 3.1"
-#~ msgstr "Actualización de la versión 3.0 a la 3.1"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
-#~ msgstr "Actualiza la configuración de Cura 2.6 a Cura 2.7."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.6 to 2.7"
-#~ msgstr "Actualización de la versión 2.6 a la 2.7"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
-#~ msgstr "Actualiza las configuraciones de Cura 2.1 a Cura 2.2."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.1 to 2.2"
-#~ msgstr "Actualización de la versión 2.1 a la 2.2"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
-#~ msgstr "Actualiza la configuración de Cura 2.2 a Cura 2.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.2 to 2.4"
-#~ msgstr "Actualización de la versión 2.2 a la 2.4"
-
-#~ msgctxt "description"
-#~ msgid "Enables ability to generate printable geometry from 2D image files."
-#~ msgstr "Habilita la capacidad de generar geometría imprimible a partir de archivos de imagen 2D."
-
-#~ msgctxt "name"
-#~ msgid "Image Reader"
-#~ msgstr "Lector de imágenes"
-
-#~ msgctxt "description"
-#~ msgid "Provides the link to the CuraEngine slicing backend."
-#~ msgstr "Proporciona el vínculo para el backend de segmentación de CuraEngine."
-
-#~ msgctxt "name"
-#~ msgid "CuraEngine Backend"
-#~ msgstr "Backend de CuraEngine"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Per Model Settings."
-#~ msgstr "Proporciona los ajustes por modelo."
-
-#~ msgctxt "name"
-#~ msgid "Per Model Settings Tool"
-#~ msgstr "Herramienta de ajustes por modelo"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading 3MF files."
-#~ msgstr "Proporciona asistencia para leer archivos 3MF."
-
-#~ msgctxt "name"
-#~ msgid "3MF Reader"
-#~ msgstr "Lector de 3MF"
-
-#~ msgctxt "description"
-#~ msgid "Provides a normal solid mesh view."
-#~ msgstr "Proporciona una vista de malla sólida normal."
-
-#~ msgctxt "name"
-#~ msgid "Solid View"
-#~ msgstr "Vista de sólidos"
-
-#~ msgctxt "description"
-#~ msgid "Allows loading and displaying G-code files."
-#~ msgstr "Permite cargar y visualizar archivos GCode."
-
-#~ msgctxt "name"
-#~ msgid "G-code Reader"
-#~ msgstr "Lector de GCode"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for exporting Cura profiles."
-#~ msgstr "Proporciona asistencia para exportar perfiles de Cura."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Writer"
-#~ msgstr "Escritor de perfiles de Cura"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing 3MF files."
-#~ msgstr "Proporciona asistencia para escribir archivos 3MF."
-
-#~ msgctxt "name"
-#~ msgid "3MF Writer"
-#~ msgstr "Escritor de 3MF"
-
-#~ msgctxt "description"
-#~ msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
-#~ msgstr "Proporciona las acciones de la máquina de las máquinas Ultimaker (como un asistente para la nivelación de la plataforma, la selección de actualizaciones, etc.)."
-
-#~ msgctxt "name"
-#~ msgid "Ultimaker machine actions"
-#~ msgstr "Acciones de la máquina Ultimaker"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing Cura profiles."
-#~ msgstr "Proporciona asistencia para la importación de perfiles de Cura."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Reader"
-#~ msgstr "Lector de perfiles de Cura"
-
#~ msgctxt "@warning:status"
#~ msgid "Please generate G-code before saving."
#~ msgstr "Genere un G-code antes de guardar."
@@ -5736,14 +6540,6 @@ msgstr "X3GWriter"
#~ msgid "Upgrade Firmware"
#~ msgstr "Actualización de firmware"
-#~ msgctxt "description"
-#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
-#~ msgstr "Permite a los fabricantes de material crear nuevos perfiles de material y calidad mediante una IU integrada."
-
-#~ msgctxt "name"
-#~ msgid "Print Profile Assistant"
-#~ msgstr "Imprimir asistente del perfil"
-
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Imprimir con un enrutador Doodle3D"
@@ -6162,7 +6958,7 @@ msgstr "X3GWriter"
#~ msgctxt "@title:window"
#~ msgid "SolidWorks plugin: Configuration"
-#~ msgstr "Complementos de SolidWorks: configuración"
+#~ msgstr "Complemento de SolidWorks: configuración"
#~ msgctxt "@title:tab"
#~ msgid "Conversion settings"
@@ -6254,7 +7050,7 @@ msgstr "X3GWriter"
#~ msgctxt "description"
#~ msgid "Helps you to install an 'export to Cura' button in Siemens NX."
-#~ msgstr "Ayuda a instalar el botón para exportar a Cura en in Siemens NX."
+#~ msgstr "Ayuda a instalar el botón para exportar a Cura en Siemens NX."
#~ msgctxt "name"
#~ msgid "Siemens NX Integration"
diff --git a/resources/i18n/es_ES/fdmextruder.def.json.po b/resources/i18n/es_ES/fdmextruder.def.json.po
index 3dfd35a0f3..5d849cfc50 100644
--- a/resources/i18n/es_ES/fdmextruder.def.json.po
+++ b/resources/i18n/es_ES/fdmextruder.def.json.po
@@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
@@ -84,7 +84,7 @@ msgstr "GCode inicial del extrusor"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
msgid "Start g-code to execute when switching to this extruder."
-msgstr ""
+msgstr "Iniciar GCode para ejecutarlo al cambiar a este extrusor."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -124,7 +124,7 @@ msgstr "GCode final del extrusor"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
msgid "End g-code to execute when switching away from this extruder."
-msgstr ""
+msgstr "Finalizar GCode para ejecutarlo al cambiar desde este extrusor."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
diff --git a/resources/i18n/es_ES/fdmprinter.def.json.po b/resources/i18n/es_ES/fdmprinter.def.json.po
index fbdf0d8f48..fbaf241481 100644
--- a/resources/i18n/es_ES/fdmprinter.def.json.po
+++ b/resources/i18n/es_ES/fdmprinter.def.json.po
@@ -5,17 +5,17 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 14:56+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Spanish\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: Spanish , Spanish \n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.2.3\n"
#: fdmprinter.def.json
msgctxt "machine_settings label"
@@ -215,6 +215,16 @@ msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
msgstr "Indica si la máquina tiene una placa de impresión caliente."
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume label"
+msgid "Has Build Volume Temperature Stabilization"
+msgstr "Tiene estabilización de temperatura del volumen de impresión"
+
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume description"
+msgid "Whether the machine is able to stabilize the build volume temperature."
+msgstr "Si la máquina puede estabilizar la temperatura del volumen de impresión."
+
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
@@ -237,7 +247,7 @@ msgstr "Número de trenes extrusores. Un tren extrusor está formado por un alim
#: fdmprinter.def.json
msgctxt "extruders_enabled_count label"
-msgid "Number of Extruders that are enabled"
+msgid "Number of Extruders That Are Enabled"
msgstr "Número de extrusores habilitados"
#: fdmprinter.def.json
@@ -247,7 +257,7 @@ msgstr "Número de trenes extrusores habilitados y configurados en el software d
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
-msgid "Outer nozzle diameter"
+msgid "Outer Nozzle Diameter"
msgstr "Diámetro exterior de la tobera"
#: fdmprinter.def.json
@@ -257,7 +267,7 @@ msgstr "Diámetro exterior de la punta de la tobera."
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
+msgid "Nozzle Length"
msgstr "Longitud de la tobera"
#: fdmprinter.def.json
@@ -267,7 +277,7 @@ msgstr "Diferencia de altura entre la punta de la tobera y la parte más baja de
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
+msgid "Nozzle Angle"
msgstr "Ángulo de la tobera"
#: fdmprinter.def.json
@@ -277,7 +287,7 @@ msgstr "Ángulo entre el plano horizontal y la parte cónica que hay justo encim
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length label"
-msgid "Heat zone length"
+msgid "Heat Zone Length"
msgstr "Longitud de la zona térmica"
#: fdmprinter.def.json
@@ -307,7 +317,7 @@ msgstr "Para controlar la temperatura desde Cura. Si va a controlar la temperatu
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed label"
-msgid "Heat up speed"
+msgid "Heat Up Speed"
msgstr "Velocidad de calentamiento"
#: fdmprinter.def.json
@@ -317,7 +327,7 @@ msgstr "Velocidad (°C/s) de calentamiento de la tobera calculada como una media
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed label"
-msgid "Cool down speed"
+msgid "Cool Down Speed"
msgstr "Velocidad de enfriamiento"
#: fdmprinter.def.json
@@ -337,7 +347,7 @@ msgstr "Tiempo mínimo que un extrusor debe permanecer inactivo antes de que la
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
+msgid "G-code Flavor"
msgstr "Tipo de GCode"
#: fdmprinter.def.json
@@ -402,7 +412,7 @@ msgstr "Utilizar o no los comandos de retracción de firmware (G10/G11) en lugar
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
+msgid "Disallowed Areas"
msgstr "Áreas no permitidas"
#: fdmprinter.def.json
@@ -422,7 +432,7 @@ msgstr "Lista de polígonos con áreas en las que la tobera no tiene permitido e
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
+msgid "Machine Head Polygon"
msgstr "Polígono del cabezal de la máquina"
#: fdmprinter.def.json
@@ -432,7 +442,7 @@ msgstr "Silueta 2D del cabezal de impresión (sin incluir las tapas del ventilad
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
-msgid "Machine head & Fan polygon"
+msgid "Machine Head & Fan Polygon"
msgstr "Polígono del cabezal de la máquina y del ventilador"
#: fdmprinter.def.json
@@ -442,7 +452,7 @@ msgstr "Silueta 2D del cabezal de impresión (incluidas las tapas del ventilador
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Altura del puente"
#: fdmprinter.def.json
@@ -472,7 +482,7 @@ msgstr "Diámetro interior de la tobera. Cambie este ajuste cuando utilice un ta
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label"
-msgid "Offset With Extruder"
+msgid "Offset with Extruder"
msgstr "Desplazamiento con extrusor"
#: fdmprinter.def.json
@@ -1020,6 +1030,17 @@ msgctxt "bottom_layers description"
msgid "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number."
msgstr "Número de capas inferiores. Al calcularlo por el grosor inferior, este valor se redondea a un número entero."
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers label"
+msgid "Initial Bottom Layers"
+msgstr "Capas inferiores iniciales"
+
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers description"
+msgid "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number."
+msgstr "El número de capas inferiores iniciales, desde la capa de impresión hacia arriba. Al calcularlo por el grosor inferior, este valor se redondea a un número"
+" entero."
+
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
@@ -1270,6 +1291,56 @@ msgctxt "z_seam_type option sharpest_corner"
msgid "Sharpest Corner"
msgstr "Esquina más pronunciada"
+#: fdmprinter.def.json
+msgctxt "z_seam_position label"
+msgid "Z Seam Position"
+msgstr "Posición de costura en Z"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position description"
+msgid "The position near where to start printing each part in a layer."
+msgstr "La posición cerca de donde comenzará la impresión de cada parte de una capa."
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backleft"
+msgid "Back Left"
+msgstr "Posterior izquierda"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option back"
+msgid "Back"
+msgstr "Posterior"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backright"
+msgid "Back Right"
+msgstr "Posterior derecha"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option right"
+msgid "Right"
+msgstr "Derecha"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontright"
+msgid "Front Right"
+msgstr "Delantera derecha"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option front"
+msgid "Front"
+msgstr "Delantera"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontleft"
+msgid "Front Left"
+msgstr "Delantera izquierda"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option left"
+msgid "Left"
+msgstr "Izquierda"
+
#: fdmprinter.def.json
msgctxt "z_seam_x label"
msgid "Z Seam X"
@@ -1297,8 +1368,8 @@ msgstr "Preferencia de esquina de costura"
#: fdmprinter.def.json
msgctxt "z_seam_corner description"
-msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
-msgstr "Controlar si las esquinas del contorno del modelo influyen en la posición de la costura. «Ninguno» significa que las esquinas no influyen en la posición de la costura. «Ocultar costura» significa que es probable que la costura se realice en una esquina interior. «Mostrar costura» significa que es probable que la costura sea en una esquina exterior. «Ocultar o mostrar costura» significa que es probable que la costura se realice en una esquina interior o exterior."
+msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner. Smart Hiding allows both inside and outside corners, but chooses inside corners more frequently, if appropriate."
+msgstr "Controlar si las esquinas del contorno del modelo influyen en la posición de la costura. «Ninguno» significa que las esquinas no influyen en la posición de la costura. «Ocultar costura» significa que es probable que la costura se realice en una esquina interior. «Mostrar costura» significa que es probable que la costura se realice en una esquina exterior. «Ocultar o mostrar costura» significa que es probable que la costura se realice en una esquina interior o exterior. «Costura inteligente» permite realizar la costura en ambas esquinas, pero opta con más frecuencia por las esquinas interiores, si resulta oportuno."
#: fdmprinter.def.json
msgctxt "z_seam_corner option z_seam_corner_none"
@@ -1320,6 +1391,11 @@ msgctxt "z_seam_corner option z_seam_corner_any"
msgid "Hide or Expose Seam"
msgstr "Ocultar o mostrar costura"
+#: fdmprinter.def.json
+msgctxt "z_seam_corner option z_seam_corner_weighted"
+msgid "Smart Hiding"
+msgstr "Costura inteligente"
+
#: fdmprinter.def.json
msgctxt "z_seam_relative label"
msgid "Z Seam Relative"
@@ -1332,13 +1408,13 @@ msgstr "Cuando se habilita, las coordenadas de la costura en z son relativas al
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic label"
-msgid "Ignore Small Z Gaps"
-msgstr "Ignorar los pequeños huecos en Z"
+msgid "No Skin in Z Gaps"
+msgstr "Sin forro en huecos en Z"
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic description"
-msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
-msgstr "Cuando el modelo tiene pequeños huecos verticales, el tiempo de cálculo puede aumentar alrededor de un 5 % para generar el forro superior e inferior en estos espacios estrechos. En tal caso, desactive este ajuste."
+msgid "When the model has small vertical gaps of only a few layers, there should normally be skin around those layers in the narrow space. Enable this setting to not generate skin if the vertical gap is very small. This improves printing time and slicing time, but technically leaves infill exposed to the air."
+msgstr "Cuando el modelo tiene pequeños huecos verticales de solo unas pocas capas, normalmente suele haber forro alrededor de ellas en el espacio estrecho. Active este ajuste para no generar forro si el hueco vertical es muy pequeño. Esto mejora el tiempo de impresión y de segmentación, pero deja el relleno expuesto al aire."
#: fdmprinter.def.json
msgctxt "skin_outline_count label"
@@ -1357,8 +1433,8 @@ msgstr "Habilitar alisado"
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
-msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
-msgstr "Pasar por la superficie superior una vez más, pero sin extruir material, para derretir la parte externa del plástico y crear una superficie más lisa."
+msgid "Go over the top surface one additional time, but this time extruding very little material. This is meant to melt the plastic on top further, creating a smoother surface. The pressure in the nozzle chamber is kept high so that the creases in the surface are filled with material."
+msgstr "Pasar por la superficie superior una vez más, pero esta vez extruyendo muy poco material, para derretir la capa superior del plástico y crear una superficie más lisa. La presión de la cámara en la boquilla se mantiene alta para que los pliegues de la superficie se llenen de material."
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
@@ -1450,6 +1526,26 @@ msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
msgstr "Cambio en la velocidad instantánea máxima durante el alisado."
+#: fdmprinter.def.json
+msgctxt "skin_overlap label"
+msgid "Skin Overlap Percentage"
+msgstr "Porcentaje de superposición del forro"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Ajuste la cantidad de superposición entre las paredes y (los extremos de) las líneas centrales del forro, como un porcentaje de los anchos de las líneas del forro y la pared más profunda. Una ligera superposición permite que las paredes estén firmemente unidas al forro. Tenga en cuenta que, con un mismo ancho de la línea del forro y la pared, cualquier porcentaje superior al 50 % ya puede provocar que cualquier forro sobrepase la pared, debido a que en ese punto la posición de la tobera del extrusor del forro ya puede sobrepasar la mitad de la pared."
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm label"
+msgid "Skin Overlap"
+msgstr "Superposición del forro"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Ajuste la cantidad de superposición entre las paredes y (los extremos de) las líneas centrales del forro. Una ligera superposición permite que las paredes estén firmemente unidas al forro. Tenga en cuenta que, con un mismo ancho de la línea del forro y la pared, cualquier valor superior a la mitad del ancho de la pared ya puede provocar que cualquier forro sobrepase la pared, debido a que en ese punto la posición de la tobera del extrusor del forro ya puede sobrepasar la mitad de la pared."
+
#: fdmprinter.def.json
msgctxt "infill label"
msgid "Infill"
@@ -1615,6 +1711,16 @@ msgctxt "infill_offset_y description"
msgid "The infill pattern is moved this distance along the Y axis."
msgstr "El patrón de relleno se mueve esta distancia a lo largo del eje Y."
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location label"
+msgid "Randomize Infill Start"
+msgstr "Comienzo de relleno aleatorio"
+
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location description"
+msgid "Randomize which infill line is printed first. This prevents one segment becoming the strongest, but it does so at the cost of an additional travel move."
+msgstr "Determine qué línea de relleno se imprime primero. Esto evita que un segmento se convierta en el más fuerte, pero a expensas de un movimiento adicional."
+
#: fdmprinter.def.json
msgctxt "infill_multiplier label"
msgid "Infill Line Multiplier"
@@ -1669,26 +1775,6 @@ msgctxt "infill_overlap_mm description"
msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
msgstr "Cantidad de superposición entre el relleno y las paredes. Una ligera superposición permite que las paredes conecten firmemente con el relleno."
-#: fdmprinter.def.json
-msgctxt "skin_overlap label"
-msgid "Skin Overlap Percentage"
-msgstr "Porcentaje de superposición del forro"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm label"
-msgid "Skin Overlap"
-msgstr "Superposición del forro"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "infill_wipe_dist label"
msgid "Infill Wipe Distance"
@@ -1869,6 +1955,16 @@ msgctxt "default_material_print_temperature description"
msgid "The default temperature used for printing. This should be the \"base\" temperature of a material. All other print temperatures should use offsets based on this value"
msgstr "La temperatura predeterminada que se utiliza para imprimir. Debería ser la temperatura básica del material. Las demás temperaturas de impresión deberían calcularse a partir de este valor"
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature label"
+msgid "Build Volume Temperature"
+msgstr "Temperatura de volumen de impresión"
+
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature description"
+msgid "The temperature of the environment to print in. If this is 0, the build volume temperature will not be adjusted."
+msgstr "La temperatura del entorno de impresión. Si el valor es 0, la temperatura de volumen de impresión no se ajustará."
+
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
msgid "Printing Temperature"
@@ -1979,6 +2075,86 @@ msgctxt "material_shrinkage_percentage description"
msgid "Shrinkage ratio in percentage."
msgstr "Índice de compresión en porcentaje."
+#: fdmprinter.def.json
+msgctxt "material_crystallinity label"
+msgid "Crystalline Material"
+msgstr "Material cristalino"
+
+#: fdmprinter.def.json
+msgctxt "material_crystallinity description"
+msgid "Is this material the type that breaks off cleanly when heated (crystalline), or is it the type that produces long intertwined polymer chains (non-crystalline)?"
+msgstr "¿Es este el tipo de material que se desprende limpiamente cuando se calienta (cristalino) o el que produce largas cadenas de polímeros entrelazadas (no cristalino)?"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position label"
+msgid "Anti-ooze Retracted Position"
+msgstr "Velocidad de retracción antirrezumado"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position description"
+msgid "How far the material needs to be retracted before it stops oozing."
+msgstr "Hasta dónde tiene que retraerse el material antes de detener el rezumado."
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed label"
+msgid "Anti-ooze Retraction Speed"
+msgstr "Velocidad de retracción antirrezumado"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed description"
+msgid "How fast the material needs to be retracted during a filament switch to prevent oozing."
+msgstr "Con qué velocidad tiene que retraerse el material durante un cambio de filamento para evitar el rezumado."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position label"
+msgid "Break Preparation Retracted Position"
+msgstr "Posición retraída de preparación de rotura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position description"
+msgid "How far the filament can be stretched before it breaks, while heated."
+msgstr "Hasta dónde puede estirarse el filamento antes de que se rompa mientras se calienta."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed label"
+msgid "Break Preparation Retraction Speed"
+msgstr "Velocidad de retracción de preparación de rotura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed description"
+msgid "How fast the filament needs to be retracted just before breaking it off in a retraction."
+msgstr "Con qué velocidad debe retraerse el filamento justo antes de romperse en una retracción."
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position label"
+msgid "Break Retracted Position"
+msgstr "Posición retraída de rotura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position description"
+msgid "How far to retract the filament in order to break it cleanly."
+msgstr "Hasta dónde debe retraerse el filamento para que se rompa limpiamente."
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed label"
+msgid "Break Retraction Speed"
+msgstr "Velocidad de retracción de rotura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed description"
+msgid "The speed at which to retract the filament in order to break it cleanly."
+msgstr "Velocidad a la que debe retraerse el filamento para que se rompa limpiamente."
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature label"
+msgid "Break Temperature"
+msgstr "Temperatura de rotura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature description"
+msgid "The temperature at which the filament is broken for a clean break."
+msgstr "Temperatura a la que se rompe el filamento de forma limpia."
+
#: fdmprinter.def.json
msgctxt "material_flow label"
msgid "Flow"
@@ -1989,6 +2165,126 @@ msgctxt "material_flow description"
msgid "Flow compensation: the amount of material extruded is multiplied by this value."
msgstr "Compensación de flujo: la cantidad de material extruido se multiplica por este valor."
+#: fdmprinter.def.json
+msgctxt "wall_material_flow label"
+msgid "Wall Flow"
+msgstr "Flujo de pared"
+
+#: fdmprinter.def.json
+msgctxt "wall_material_flow description"
+msgid "Flow compensation on wall lines."
+msgstr "Compensación de flujo en líneas de pared."
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow label"
+msgid "Outer Wall Flow"
+msgstr "Flujo de pared exterior"
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow description"
+msgid "Flow compensation on the outermost wall line."
+msgstr "Compensación de flujo en la línea de pared más externa."
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow label"
+msgid "Inner Wall(s) Flow"
+msgstr "Flujo de pared o paredes interiores"
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow description"
+msgid "Flow compensation on wall lines for all wall lines except the outermost one."
+msgstr "Compensación de flujo en líneas de pared para todas las líneas excepto la más externa."
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow label"
+msgid "Top/Bottom Flow"
+msgstr "Flujo superior o inferior"
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow description"
+msgid "Flow compensation on top/bottom lines."
+msgstr "Compensación de flujo en las líneas superiores o inferiores."
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow label"
+msgid "Top Surface Skin Flow"
+msgstr "Flujo de forro de superficie superior"
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow description"
+msgid "Flow compensation on lines of the areas at the top of the print."
+msgstr "Compensación de flujo en líneas de las áreas superiores de la impresión."
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow label"
+msgid "Infill Flow"
+msgstr "Flujo de relleno"
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow description"
+msgid "Flow compensation on infill lines."
+msgstr "Compensación de flujo en líneas de relleno."
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow label"
+msgid "Skirt/Brim Flow"
+msgstr "Flujo de falda/borde"
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow description"
+msgid "Flow compensation on skirt or brim lines."
+msgstr "Compensación de flujo en líneas de falda o borde."
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow label"
+msgid "Support Flow"
+msgstr "Flujo de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow description"
+msgid "Flow compensation on support structure lines."
+msgstr "Compensación de flujo en líneas de estructura de soporte."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow label"
+msgid "Support Interface Flow"
+msgstr "Flujo de interfaz de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow description"
+msgid "Flow compensation on lines of support roof or floor."
+msgstr "Compensación de flujo en líneas de techo o suelo de soporte."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow label"
+msgid "Support Roof Flow"
+msgstr "Flujo de techo de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow description"
+msgid "Flow compensation on support roof lines."
+msgstr "Compensación de flujo en líneas de techo de soporte."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow label"
+msgid "Support Floor Flow"
+msgstr "Flujo de suelo de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow description"
+msgid "Flow compensation on support floor lines."
+msgstr "Compensación de flujo en líneas de suelo de soporte."
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow label"
+msgid "Prime Tower Flow"
+msgstr "Flujo de la torre auxiliar"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow description"
+msgid "Flow compensation on prime tower lines."
+msgstr "Compensación de flujo en líneas de la torre auxiliar."
+
#: fdmprinter.def.json
msgctxt "material_flow_layer_0 label"
msgid "Initial Layer Flow"
@@ -2106,7 +2402,7 @@ msgstr "Limitar las retracciones de soporte"
#: fdmprinter.def.json
msgctxt "limit_support_retractions description"
-msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure."
msgstr "Omitir la retracción al moverse de soporte a soporte en línea recta. Habilitar este ajuste ahorra tiempo de impresión pero puede ocasionar un encordado excesivo en la estructura de soporte."
#: fdmprinter.def.json
@@ -2127,7 +2423,7 @@ msgstr "Distancia de retracción del cambio de tobera"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
msgid "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr ""
+msgstr "Distancia de la retracción al cambiar los extrusores. Utilice el valor 0 para que no haya retracción. Por norma general, este valor debe ser igual a la longitud de la zona de calentamiento."
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_speeds label"
@@ -2159,6 +2455,16 @@ msgctxt "switch_extruder_prime_speed description"
msgid "The speed at which the filament is pushed back after a nozzle switch retraction."
msgstr "Velocidad a la que se retrae el filamento durante una retracción del cambio de tobera."
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount label"
+msgid "Nozzle Switch Extra Prime Amount"
+msgstr "Volumen de cebado adicional tras cambio de tobera"
+
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount description"
+msgid "Extra material to prime after nozzle switching."
+msgstr "Material adicional que debe cebarse tras el cambio de tobera."
+
#: fdmprinter.def.json
msgctxt "speed label"
msgid "Speed"
@@ -2350,14 +2656,14 @@ msgid "The speed at which the skirt and brim are printed. Normally this is done
msgstr "Velocidad a la que se imprimen la falda y el borde. Normalmente, esto se hace a la velocidad de la capa inicial, pero a veces es posible que se prefiera imprimir la falda o el borde a una velocidad diferente."
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override label"
-msgid "Maximum Z Speed"
-msgstr "Velocidad máxima de Z"
+msgctxt "speed_z_hop label"
+msgid "Z Hop Speed"
+msgstr "Velocidad del salto en Z"
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override description"
-msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
-msgstr "Velocidad máxima a la que se mueve la placa de impresión. Definir este valor en 0 hace que la impresión utilice los valores predeterminados de la velocidad máxima de Z."
+msgctxt "speed_z_hop description"
+msgid "The speed at which the vertical Z movement is made for Z Hops. This is typically lower than the print speed since the build plate or machine's gantry is harder to move."
+msgstr "Velocidad a la que se realiza el movimiento vertical en la dirección Z para los saltos en Z. Suele ser inferior a la velocidad de impresión porque la placa de impresión o el puente de la máquina es más difícil de desplazar."
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers label"
@@ -2787,7 +3093,7 @@ msgstr "Modo Peinada"
#: fdmprinter.def.json
msgctxt "retraction_combing description"
msgid "Combing keeps the nozzle within already printed areas when traveling. This results in slightly longer travel moves but reduces the need for retractions. If combing is off, the material will retract and the nozzle moves in a straight line to the next point. It is also possible to avoid combing over top/bottom skin areas or to only comb within the infill."
-msgstr ""
+msgstr "La opción de peinada mantiene la tobera dentro de las áreas ya impresas al desplazarse. Esto ocasiona movimientos de desplazamiento ligeramente más largos, pero reduce la necesidad de realizar retracciones. Si se desactiva la opción de peinada, el material se retraerá y la tobera se moverá en línea recta hasta el siguiente punto. Otra posibilidad es evitar la peinada en áreas de forro superiores/inferiores o peinar solo en el relleno."
#: fdmprinter.def.json
msgctxt "retraction_combing option off"
@@ -2859,16 +3165,6 @@ msgctxt "travel_avoid_distance description"
msgid "The distance between the nozzle and already printed parts when avoiding during travel moves."
msgstr "Distancia entre la tobera y las partes ya impresas, cuando se evita durante movimientos de desplazamiento."
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position label"
-msgid "Start Layers with the Same Part"
-msgstr "Comenzar capas con la misma parte"
-
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position description"
-msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
-msgstr "En cada capa, comenzar imprimiendo el objeto cerca del mismo punto, de forma que no se comienza una capa imprimiendo la pieza en la que finalizó la capa anterior. Esto permite mejorar los voladizos y las partes pequeñas, a costa de un mayor tiempo de impresión."
-
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
@@ -2929,6 +3225,16 @@ msgctxt "retraction_hop_after_extruder_switch description"
msgid "After the machine switched from one extruder to the other, the build plate is lowered to create clearance between the nozzle and the print. This prevents the nozzle from leaving oozed material on the outside of a print."
msgstr "Cuando la máquina cambia de un extrusor a otro, la placa de impresión se baja para crear holgura entre la tobera y la impresión. Esto impide que el material rezumado quede fuera de la impresión."
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height label"
+msgid "Z Hop After Extruder Switch Height"
+msgstr "Salto en Z tras altura de cambio de extrusor"
+
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height description"
+msgid "The height difference when performing a Z Hop after extruder switch."
+msgstr "Diferencia de altura cuando se realiza un salto en Z después de un cambio de extrusor."
+
#: fdmprinter.def.json
msgctxt "cooling label"
msgid "Cooling"
@@ -3199,6 +3505,11 @@ msgctxt "support_pattern option cross"
msgid "Cross"
msgstr "Cruz"
+#: fdmprinter.def.json
+msgctxt "support_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Giroide"
+
#: fdmprinter.def.json
msgctxt "support_wall_count label"
msgid "Support Wall Line Count"
@@ -3260,14 +3571,14 @@ msgid "Distance between the printed initial layer support structure lines. This
msgstr "Distancia entre las líneas de estructuras del soporte de la capa inicial impresas. Este ajuste se calcula por la densidad del soporte."
#: fdmprinter.def.json
-msgctxt "support_infill_angle label"
-msgid "Support Infill Line Direction"
+msgctxt "support_infill_angles label"
+msgid "Support Infill Line Directions"
msgstr "Dirección de línea de relleno de soporte"
#: fdmprinter.def.json
-msgctxt "support_infill_angle description"
-msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
-msgstr "Orientación del patrón de relleno para soportes. El patrón de relleno de soporte se gira en el plano horizontal."
+msgctxt "support_infill_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees."
+msgstr "Una lista de los valores enteros de las direcciones de línea que se van a utilizar. Los elementos de la lista se usan secuencialmente a medida que avanzan las capas y cuando se alcanza el final de la lista, comienza de nuevo desde el principio. Los elementos de la lista están separados por comas y toda la lista aparece entre corchetes. El valor predeterminado es una lista vacía, lo que significa que se usa el ángulo predeterminado de 0 grados."
#: fdmprinter.def.json
msgctxt "support_brim_enable label"
@@ -3396,8 +3707,8 @@ msgstr "Distancia de unión del soporte"
#: fdmprinter.def.json
msgctxt "support_join_distance description"
-msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
-msgstr "Distancia máxima entre las estructuras del soporte en las direcciones X/Y. Cuando estructuras separadas están más cerca entre sí que de este valor, las estructuras se combinan en una."
+msgid "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one."
+msgstr "Distancia máxima entre las estructuras del soporte en las direcciones X/Y. Cuando las estructuras separadas están más cerca entre sí que este valor, se combinan en una."
#: fdmprinter.def.json
msgctxt "support_offset label"
@@ -3442,12 +3753,12 @@ msgstr "Altura del relleno de soporte de una determinada densidad antes de cambi
#: fdmprinter.def.json
msgctxt "minimum_support_area label"
msgid "Minimum Support Area"
-msgstr ""
+msgstr "Área del soporte mínima"
#: fdmprinter.def.json
msgctxt "minimum_support_area description"
msgid "Minimum area size for support polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgstr "Tamaño del área mínima para los polígonos del soporte. No se generarán polígonos que posean un área de menor tamaño que este valor."
#: fdmprinter.def.json
msgctxt "support_interface_enable label"
@@ -3677,62 +3988,93 @@ msgstr "Zigzag"
#: fdmprinter.def.json
msgctxt "minimum_interface_area label"
msgid "Minimum Support Interface Area"
-msgstr ""
+msgstr "Área de la interfaz de soporte mínima"
#: fdmprinter.def.json
msgctxt "minimum_interface_area description"
-msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Tamaño del área mínima para los polígonos de la interfaz de soporte. Los polígonos que posean un área de menor tamaño que este valor se imprimirán como"
+" soporte normal."
#: fdmprinter.def.json
msgctxt "minimum_roof_area label"
msgid "Minimum Support Roof Area"
-msgstr ""
+msgstr "Área de los techos del soporte mínima"
#: fdmprinter.def.json
msgctxt "minimum_roof_area description"
-msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Tamaño del área mínima para los techos del soporte. Los polígonos que posean un área de menor tamaño que este valor se imprimirán como soporte normal."
#: fdmprinter.def.json
msgctxt "minimum_bottom_area label"
msgid "Minimum Support Floor Area"
-msgstr ""
+msgstr "Área de los suelos del soporte mínima"
#: fdmprinter.def.json
msgctxt "minimum_bottom_area description"
-msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Tamaño del área mínima para los suelos del soporte. Los polígonos que posean un área de menor tamaño que este valor se imprimirán como soporte normal."
#: fdmprinter.def.json
msgctxt "support_interface_offset label"
msgid "Support Interface Horizontal Expansion"
-msgstr ""
+msgstr "Expansión horizontal de la interfaz de soporte"
#: fdmprinter.def.json
msgctxt "support_interface_offset description"
msgid "Amount of offset applied to the support interface polygons."
-msgstr ""
+msgstr "Cantidad de desplazamiento aplicado a los polígonos de la interfaz de soporte."
#: fdmprinter.def.json
msgctxt "support_roof_offset label"
msgid "Support Roof Horizontal Expansion"
-msgstr ""
+msgstr "Expansión horizontal de los techos del soporte"
#: fdmprinter.def.json
msgctxt "support_roof_offset description"
msgid "Amount of offset applied to the roofs of the support."
-msgstr ""
+msgstr "Cantidad de desplazamiento aplicado a los techos del soporte."
#: fdmprinter.def.json
msgctxt "support_bottom_offset label"
msgid "Support Floor Horizontal Expansion"
-msgstr ""
+msgstr "Expansión horizontal de los suelos de soporte"
#: fdmprinter.def.json
msgctxt "support_bottom_offset description"
msgid "Amount of offset applied to the floors of the support."
-msgstr ""
+msgstr "Cantidad de desplazamiento aplicado a los suelos del soporte."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles label"
+msgid "Support Interface Line Directions"
+msgstr "Direcciones de línea de interfaz de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Una lista de los valores enteros de las direcciones de línea que se van a utilizar. Los elementos de la lista se usan secuencialmente a medida que avanzan las capas y cuando se alcanza el final de la lista, comienza de nuevo desde el principio. Los elementos de la lista están separados por comas y toda la lista aparece entre corchetes. El valor predeterminado es una lista vacía, lo que significa que se utilizan los ángulos estándar (que varían entre 45 y 135 grados si las interfaces son bastante gruesas o de 90 grados en otro caso)."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles label"
+msgid "Support Roof Line Directions"
+msgstr "Direcciones de línea del techo de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Una lista de los valores enteros de las direcciones de línea que se van a utilizar. Los elementos de la lista se usan secuencialmente a medida que avanzan las capas y cuando se alcanza el final de la lista, comienza de nuevo desde el principio. Los elementos de la lista están separados por comas y toda la lista aparece entre corchetes. El valor predeterminado es una lista vacía, lo que significa que se utilizan los ángulos estándar (que varían entre 45 y 135 grados si las interfaces son bastante gruesas o de 90 grados en otro caso)."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles label"
+msgid "Support Floor Line Directions"
+msgstr "Direcciones de línea del suelo de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Una lista de los valores enteros de las direcciones de línea que se van a utilizar. Los elementos de la lista se usan secuencialmente a medida que avanzan las capas y cuando se alcanza el final de la lista, comienza de nuevo desde el principio. Los elementos de la lista están separados por comas y toda la lista aparece entre corchetes. El valor predeterminado es una lista vacía, lo que significa que se utilizan los ángulos estándar (que varían entre 45 y 135 grados si las interfaces son bastante gruesas o de 90 grados en otro caso)."
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
@@ -3775,14 +4117,14 @@ msgid "The diameter of a special tower."
msgstr "Diámetro de una torre especial."
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter label"
-msgid "Minimum Diameter"
-msgstr "Diámetro mínimo"
+msgctxt "support_tower_maximum_supported_diameter label"
+msgid "Maximum Tower-Supported Diameter"
+msgstr "Diámetro máximo soportado por la torre"
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter description"
-msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
-msgstr "Diámetro mínimo en las direcciones X/Y de una pequeña área que soportará una torre de soporte especializada."
+msgctxt "support_tower_maximum_supported_diameter description"
+msgid "Maximum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+msgstr "Diámetro máximo en las direcciones X/Y de una pequeña área que debe ser soportada por una torre de soporte especializada."
#: fdmprinter.def.json
msgctxt "support_tower_roof_angle label"
@@ -4278,16 +4620,6 @@ msgctxt "prime_tower_enable description"
msgid "Print a tower next to the print which serves to prime the material after each nozzle switch."
msgstr "Imprimir una torre junto a la impresión que sirve para preparar el material tras cada cambio de tobera."
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular label"
-msgid "Circular Prime Tower"
-msgstr "Torre auxiliar circular"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular description"
-msgid "Make the prime tower as a circular shape."
-msgstr "Hacer que la torre auxiliar sea circular."
-
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
@@ -4328,16 +4660,6 @@ msgctxt "prime_tower_position_y description"
msgid "The y coordinate of the position of the prime tower."
msgstr "Coordenada Y de la posición de la torre auxiliar."
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow label"
-msgid "Prime Tower Flow"
-msgstr "Flujo de la torre auxiliar"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow description"
-msgid "Flow compensation: the amount of material extruded is multiplied by this value."
-msgstr "Compensación de flujo: la cantidad de material extruido se multiplica por este valor."
-
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
@@ -4348,6 +4670,16 @@ msgctxt "prime_tower_wipe_enabled description"
msgid "After printing the prime tower with one nozzle, wipe the oozed material from the other nozzle off on the prime tower."
msgstr "Tras imprimir la torre auxiliar con una tobera, limpie el material rezumado de la otra tobera de la torre auxiliar."
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable label"
+msgid "Prime Tower Brim"
+msgstr "Borde de la torre auxiliar"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable description"
+msgid "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type."
+msgstr "Puede que las torres auxiliares necesiten la adherencia adicional que proporciona un borde, aunque no sea requisito del modelo. Actualmente, no se puede usar con el tipo de adherencia «balsa»."
+
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
msgid "Enable Ooze Shield"
@@ -4468,6 +4800,36 @@ msgctxt "remove_empty_first_layers description"
msgid "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle."
msgstr "Eliminar (si las hubiera) las capas vacías por debajo de la primera capa impresa. Deshabilitar este ajuste puede hacer que aparezcan primeras capas vacías si el ajuste de tolerancia de segmentación está establecido en Exclusiva o Medio."
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Resolución máxima"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "El tamaño mínimo de un segmento de línea tras la segmentación. Si se aumenta, la resolución de la malla será menor. Esto puede permitir a la impresora mantener la velocidad que necesita para procesar GCode y aumentará la velocidad de segmentación al eliminar detalles de la malla que, de todas formas, no puede procesar."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution label"
+msgid "Maximum Travel Resolution"
+msgstr "Resolución de desplazamiento máximo"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution description"
+msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
+msgstr "El tamaño mínimo de un segmento de línea de desplazamiento tras la segmentación. Si se aumenta, los movimientos de desplazamiento tendrán esquinas menos suavizadas. Esto puede le permite a la impresora mantener la velocidad que necesita para procesar GCode pero puede ocasionar que evitar el modelo sea menos preciso."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation label"
+msgid "Maximum Deviation"
+msgstr "Desviación máxima"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation description"
+msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true."
+msgstr "La desviación máxima permitida al reducir la resolución en el ajuste de la resolución máxima. Si se aumenta el valor, la impresión será menos precisa pero el GCode será más pequeño. La desviación máxima es un límite para la resolución máxima, por lo que si las dos entran en conflicto, la desviación máxima siempre tendrá prioridad."
+
#: fdmprinter.def.json
msgctxt "blackmagic label"
msgid "Special Modes"
@@ -4630,8 +4992,8 @@ msgstr "Contornos espiralizados suaves"
#: fdmprinter.def.json
msgctxt "smooth_spiralized_contours description"
-msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
-msgstr "Suavice los contornos espiralizados para reducir la visibilidad de la costura Z (la costura Z debería ser apenas visible en la impresora pero seguirá siendo visible en la vista de capas). Tenga en cuenta que la suavización tenderá a desdibujar detalles finos de la superficie."
+msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+msgstr "Suaviza los contornos espiralizados para reducir la visibilidad de la costura Z (la costura Z debería ser apenas visible en la impresora pero seguirá siendo visible en la vista de capas). Tenga en cuenta que la suavización tenderá a desdibujar detalles finos de la superficie."
#: fdmprinter.def.json
msgctxt "relative_extrusion label"
@@ -4843,26 +5205,6 @@ msgctxt "minimum_polygon_circumference description"
msgid "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details."
msgstr "Se filtran los polígonos en capas segmentadas que tienen una circunferencia más pequeña que esta. Los valores más pequeños suponen una resolución de malla mayor a costa de un tiempo de segmentación. Está indicado, sobre todo, para impresoras SLA y modelos 3D muy pequeños con muchos detalles."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Resolución máxima"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "El tamaño mínimo de un segmento de línea tras la segmentación. Si se aumenta, la resolución de la malla será menor. Esto puede permitir a la impresora mantener la velocidad que necesita para procesar GCode y aumentará la velocidad de segmentación al eliminar detalles de la malla que, de todas formas, no puede procesar."
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution label"
-msgid "Maximum Travel Resolution"
-msgstr "Resolución de desplazamiento máximo"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution description"
-msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
-msgstr "El tamaño mínimo de un segmento de línea de desplazamiento tras la segmentación. Si se aumenta, los movimientos de desplazamiento tendrán esquinas menos suavizadas. Esto puede le permite a la impresora mantener la velocidad que necesita para procesar GCode pero puede ocasionar que evitar el modelo sea menos preciso."
-
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5003,16 +5345,6 @@ msgctxt "coasting_speed description"
msgid "The speed by which to move during coasting, relative to the speed of the extrusion path. A value slightly under 100% is advised, since during the coasting move the pressure in the bowden tube drops."
msgstr "Velocidad a la que se desplaza durante el depósito por inercia con relación a la velocidad de la trayectoria de extrusión. Se recomienda un valor ligeramente por debajo del 100%, ya que la presión en el tubo guía disminuye durante el movimiento depósito por inercia."
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation label"
-msgid "Alternate Skin Rotation"
-msgstr "Alternar la rotación del forro"
-
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation description"
-msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
-msgstr "Alterna la dirección en la que se imprimen las capas superiores/inferiores. Normalmente, se imprimen únicamente en diagonal. Este ajuste añade las direcciones solo X y solo Y."
-
#: fdmprinter.def.json
msgctxt "cross_infill_pocket_size label"
msgid "Cross 3D Pocket Size"
@@ -5120,8 +5452,8 @@ msgstr "Activar soporte cónico"
#: fdmprinter.def.json
msgctxt "support_conical_enabled description"
-msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
-msgstr "Función experimental: hace áreas de soporte más pequeñas en la parte inferior que en el voladizo."
+msgid "Make support areas smaller at the bottom than at the overhang."
+msgstr "Hace que las áreas de soporte sean más pequeñas en la parte inferior que en el voladizo."
#: fdmprinter.def.json
msgctxt "support_conical_angle label"
@@ -5185,23 +5517,24 @@ msgstr "Distancia media entre los puntos aleatorios introducidos en cada segment
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
-msgid "Flow rate compensation max extrusion offset"
+msgid "Flow Rate Compensation Max Extrusion Offset"
msgstr "Desplazamiento de extrusión máximo del factor de compensación del caudal"
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
-msgid "The maximum distance in mm to compensate."
-msgstr "Distancia máxima en mm que se va a compensar."
+msgid "The maximum distance in mm to move the filament to compensate for changes in flow rate."
+msgstr "La distancia máxima en mm para mover el filamento con el fin de compensar los cambios en el caudal."
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor label"
-msgid "Flow rate compensation factor"
+msgid "Flow Rate Compensation Factor"
msgstr "Factor de compensación del caudal"
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor description"
-msgid "The multiplication factor for the flow rate -> distance translation."
-msgstr "La multiplicación factor por caudal da como resultado la conversión de distancia."
+msgid "How far to move the filament in order to compensate for changes in flow rate, as a percentage of how far the filament would move in one second of extrusion."
+msgstr "La distancia para mover el filamento con el fin de compensar los cambios en el caudal, como porcentaje de la distancia a la que se movería el filamento"
+" en un segundo de extrusión."
#: fdmprinter.def.json
msgctxt "wireframe_enabled label"
@@ -5464,7 +5797,7 @@ msgstr "Distancia entre la tobera y líneas descendentes en horizontal. Cuanto m
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr "Utilizar capas de adaptación"
#: fdmprinter.def.json
@@ -5474,7 +5807,7 @@ msgstr "Las capas de adaptación calculan las alturas de las capas dependiendo d
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation label"
-msgid "Adaptive layers maximum variation"
+msgid "Adaptive Layers Maximum Variation"
msgstr "Variación máxima de las capas de adaptación"
#: fdmprinter.def.json
@@ -5484,7 +5817,7 @@ msgstr "La diferencia de altura máxima permitida en comparación con la altura
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation_step label"
-msgid "Adaptive layers variation step size"
+msgid "Adaptive Layers Variation Step Size"
msgstr "Tamaño de pasos de variación de las capas de adaptación"
#: fdmprinter.def.json
@@ -5494,13 +5827,14 @@ msgstr "La diferencia de altura de la siguiente altura de capa en comparación c
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
-msgstr "Umbral de las capas de adaptación"
+msgid "Adaptive Layers Topography Size"
+msgstr "Tamaño de la topografía de las capas de adaptación"
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold description"
-msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
-msgstr "Umbral para usar o no una capa más pequeña. Este número se compara con el curtido de la pendiente más empinada de una capa."
+msgid "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together."
+msgstr "Distancia horizontal objetivo entre dos capas adyacentes. Si se reduce este ajuste, se tendrán que utilizar capas más finas para acercar más los bordes"
+" de las capas."
#: fdmprinter.def.json
msgctxt "wall_overhang_angle label"
@@ -5509,8 +5843,9 @@ msgstr "Ángulo de voladizo de pared"
#: fdmprinter.def.json
msgctxt "wall_overhang_angle description"
-msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
-msgstr "Las paredes con un ángulo de voladizo mayor que este se imprimirán con los ajustes de voladizo de pared. Cuando el valor sea 90, no se aplicará la condición de voladizo a la pared."
+msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging. Overhang that gets supported by support will not be treated as overhang either."
+msgstr "Las paredes con un ángulo de voladizo mayor que este se imprimirán con los ajustes de voladizo de pared. Cuando el valor sea 90, no se aplicará la condición"
+" de voladizo a la pared. El voladizo que se apoya en el soporte tampoco se tratará como voladizo."
#: fdmprinter.def.json
msgctxt "wall_overhang_speed_factor label"
@@ -5712,6 +6047,197 @@ msgctxt "bridge_fan_speed_3 description"
msgid "Percentage fan speed to use when printing the third bridge skin layer."
msgstr "Velocidad del ventilador en porcentaje que se utiliza para imprimir la tercera capa del forro del puente."
+#: fdmprinter.def.json
+msgctxt "clean_between_layers label"
+msgid "Wipe Nozzle Between Layers"
+msgstr "Limpiar tobera entre capas"
+
+#: fdmprinter.def.json
+msgctxt "clean_between_layers description"
+msgid "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working."
+msgstr "Posibilidad de incluir GCode de limpieza de tobera entre capas. Habilitar este ajuste puede influir en el comportamiento de retracción en el cambio de capa. Utilice los ajustes de retracción de limpieza para controlar la retracción en las capas donde la secuencia de limpieza estará en curso."
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe label"
+msgid "Material Volume Between Wipes"
+msgstr "Volumen de material entre limpiezas"
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe description"
+msgid "Maximum material, that can be extruded before another nozzle wipe is initiated."
+msgstr "Material máximo que puede extruirse antes de que se inicie otra limpieza de tobera."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable label"
+msgid "Wipe Retraction Enable"
+msgstr "Habilitación de retracción de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable description"
+msgid "Retract the filament when the nozzle is moving over a non-printed area."
+msgstr "Retrae el filamento cuando la tobera se mueve sobre un área no impresa."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount label"
+msgid "Wipe Retraction Distance"
+msgstr "Distancia de retracción de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount description"
+msgid "Amount to retract the filament so it does not ooze during the wipe sequence."
+msgstr "Cantidad para retraer el filamento para que no rezume durante la secuencia de limpieza."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount label"
+msgid "Wipe Retraction Extra Prime Amount"
+msgstr "Cantidad de cebado adicional de retracción de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount description"
+msgid "Some material can ooze away during a wipe travel moves, which can be compensated for here."
+msgstr "Algunos materiales pueden rezumar durante el movimiento de un desplazamiento de limpieza, lo cual se puede corregir aquí."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed label"
+msgid "Wipe Retraction Speed"
+msgstr "Velocidad de retracción de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed description"
+msgid "The speed at which the filament is retracted and primed during a wipe retraction move."
+msgstr "Velocidad a la que se retrae el filamento y se prepara durante un movimiento de retracción de limpieza."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed label"
+msgid "Wipe Retraction Retract Speed"
+msgstr "Velocidad de retracción en retracción de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed description"
+msgid "The speed at which the filament is retracted during a wipe retraction move."
+msgstr "Velocidad a la que se retrae el filamento durante un movimiento de retracción de limpieza."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed label"
+msgid "Retraction Prime Speed"
+msgstr "Velocidad de cebado de retracción"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed description"
+msgid "The speed at which the filament is primed during a wipe retraction move."
+msgstr "Velocidad a la que se prepara el filamento durante un movimiento de retracción de limpieza."
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause label"
+msgid "Wipe Pause"
+msgstr "Pausar limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause description"
+msgid "Pause after the unretract."
+msgstr "Pausa después de no haber retracción."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable label"
+msgid "Wipe Z Hop When Retracted"
+msgstr "Limpiar salto en Z en la retracción"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable description"
+msgid "Whenever a retraction is done, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate."
+msgstr "Siempre que se realiza una retracción, la placa de impresión se baja para crear holgura entre la tobera y la impresión. Impide que la tobera golpee la impresión durante movimientos de desplazamiento, reduciendo las posibilidades de alcanzar la impresión de la placa de impresión."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount label"
+msgid "Wipe Z Hop Height"
+msgstr "Limpiar altura del salto en Z"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount description"
+msgid "The height difference when performing a Z Hop."
+msgstr "Diferencia de altura cuando se realiza un salto en Z."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed label"
+msgid "Wipe Hop Speed"
+msgstr "Limpiar velocidad de salto"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed description"
+msgid "Speed to move the z-axis during the hop."
+msgstr "Velocidad para mover el eje Z durante el salto."
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x label"
+msgid "Wipe Brush X Position"
+msgstr "Limpiar posición X de cepillo"
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x description"
+msgid "X location where wipe script will start."
+msgstr "Ubicación X donde se iniciará la secuencia de limpieza."
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count label"
+msgid "Wipe Repeat Count"
+msgstr "Recuento de repeticiones de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count description"
+msgid "Number of times to move the nozzle across the brush."
+msgstr "Número de movimientos de la tobera a lo largo del cepillo."
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance label"
+msgid "Wipe Move Distance"
+msgstr "Distancia de movimiento de limpieza"
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance description"
+msgid "The distance to move the head back and forth across the brush."
+msgstr "La distancia para mover el cabezal hacia adelante y hacia atrás a lo largo del cepillo."
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size label"
+msgid "Small Hole Max Size"
+msgstr "Tamaño máximo de agujero pequeño"
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size description"
+msgid "Holes and part outlines with a diameter smaller than this will be printed using Small Feature Speed."
+msgstr "Los agujeros y contornos de las piezas con un diámetro menor que estos se imprimen utilizando la función Velocidad de pequeñas partes."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length label"
+msgid "Small Feature Max Length"
+msgstr "Longitud máxima de pequeñas partes"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length description"
+msgid "Feature outlines that are shorter than this length will be printed using Small Feature Speed."
+msgstr "Los contornos de las partes que sean más cortos que esta longitud se imprimen utilizando la función Velocidad de pequeñas partes."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor label"
+msgid "Small Feature Speed"
+msgstr "Velocidad de pequeñas partes"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor description"
+msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "Las pequeñas partes se imprimirán a este porcentaje de su velocidad de impresión normal. Una impresión más lenta puede mejorar la adhesión y la precisión."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 label"
+msgid "Small Feature Initial Layer Speed"
+msgstr "Velocidad de la capa inicial de partes pequeñas"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 description"
+msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "Las pequeñas partes de la primera capa se imprimirán a este porcentaje de su velocidad de impresión normal. Una impresión más lenta puede mejorar la adhesión"
+" y la precisión."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5772,6 +6298,218 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Matriz de transformación que se aplicará al modelo cuando se cargue desde el archivo."
+#~ msgctxt "minimum_interface_area description"
+#~ msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Tamaño del área mínima para los polígonos de la interfaz de soporte. No se generarán polígonos que posean un área de menor tamaño que este valor."
+
+#~ msgctxt "minimum_roof_area description"
+#~ msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Tamaño del área mínima para los techos del soporte. No se generarán polígonos que posean un área de menor tamaño que este valor."
+
+#~ msgctxt "minimum_bottom_area description"
+#~ msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Tamaño del área mínima para los suelos del soporte. No se generarán polígonos que posean un área de menor tamaño que este valor."
+
+#~ msgctxt "skin_alternate_rotation label"
+#~ msgid "Alternate Skin Rotation"
+#~ msgstr "Alternar la rotación del forro"
+
+#~ msgctxt "skin_alternate_rotation description"
+#~ msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
+#~ msgstr "Alterna la dirección en la que se imprimen las capas superiores/inferiores. Normalmente, se imprimen únicamente en diagonal. Este ajuste añade las direcciones solo X y solo Y."
+
+#~ msgctxt "flow_rate_max_extrusion_offset label"
+#~ msgid "Flow rate compensation max extrusion offset"
+#~ msgstr "Desplazamiento de extrusión máximo del factor de compensación del caudal"
+
+#~ msgctxt "flow_rate_max_extrusion_offset description"
+#~ msgid "The maximum distance in mm to compensate."
+#~ msgstr "Distancia máxima en mm que se va a compensar."
+
+#~ msgctxt "flow_rate_extrusion_offset_factor label"
+#~ msgid "Flow rate compensation factor"
+#~ msgstr "Factor de compensación del caudal"
+
+#~ msgctxt "flow_rate_extrusion_offset_factor description"
+#~ msgid "The multiplication factor for the flow rate -> distance translation."
+#~ msgstr "La multiplicación factor por caudal da como resultado la conversión de distancia."
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive Layers Threshold"
+#~ msgstr "Umbral de las capas de adaptación"
+
+#~ msgctxt "adaptive_layer_height_threshold description"
+#~ msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+#~ msgstr "Umbral para usar o no una capa más pequeña. Este número se compara con el curtido de la pendiente más empinada de una capa."
+
+#~ msgctxt "wall_overhang_angle description"
+#~ msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
+#~ msgstr "Las paredes con un ángulo de voladizo mayor que este se imprimirán con los ajustes de voladizo de pared. Cuando el valor sea 90, no se aplicará la condición de voladizo a la pared."
+
+#~ msgctxt "small_feature_speed_factor description"
+#~ msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "Las pequeñas partes se imprimirán a este porcentaje de su velocidad de impresión normal. Una impresión más lenta puede mejorar la adhesión y la precisión."
+
+#~ msgctxt "small_feature_speed_factor_0 label"
+#~ msgid "First Layer Speed"
+#~ msgstr "Velocidad de primera capa"
+
+#~ msgctxt "small_feature_speed_factor_0 description"
+#~ msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "Las pequeñas partes de la primera capa se imprimirán a este porcentaje de su velocidad de impresión normal. Una impresión más lenta puede mejorar la adhesión y la precisión."
+
+#~ msgctxt "ironing_enabled description"
+#~ msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
+#~ msgstr "Pasar por la superficie superior una vez más, pero sin extruir material, para derretir la parte externa del plástico y crear una superficie más lisa."
+
+#~ msgctxt "start_layers_at_same_position label"
+#~ msgid "Start Layers with the Same Part"
+#~ msgstr "Comenzar capas con la misma parte"
+
+#~ msgctxt "start_layers_at_same_position description"
+#~ msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
+#~ msgstr "En cada capa, comenzar imprimiendo el objeto cerca del mismo punto, de forma que no se comienza una capa imprimiendo la pieza en la que finalizó la capa anterior. Esto permite mejorar los voladizos y las partes pequeñas, a costa de un mayor tiempo de impresión."
+
+#~ msgctxt "support_infill_angles description"
+#~ msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
+#~ msgstr "Orientación del patrón de relleno para soportes. El patrón de relleno de soporte se gira en el plano horizontal."
+
+#~ msgctxt "meshfix_maximum_deviation description"
+#~ msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller."
+#~ msgstr "La desviación máxima permitida al reducir la resolución en el ajuste de resolución máxima. Si se aumenta el valor, la impresión será menos precisa pero el GCode será más pequeño."
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code Flavour"
+#~ msgstr "Tipo de GCode"
+
+#~ msgctxt "z_seam_corner description"
+#~ msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
+#~ msgstr "Controlar si las esquinas del contorno del modelo influyen en la posición de la costura. «Ninguno» significa que las esquinas no influyen en la posición de la costura. «Ocultar costura» significa que es probable que la costura se realice en una esquina interior. «Mostrar costura» significa que es probable que la costura sea en una esquina exterior. «Ocultar o mostrar costura» significa que es probable que la costura se realice en una esquina interior o exterior."
+
+#~ msgctxt "skin_no_small_gaps_heuristic label"
+#~ msgid "Ignore Small Z Gaps"
+#~ msgstr "Ignorar los pequeños huecos en Z"
+
+#~ msgctxt "skin_no_small_gaps_heuristic description"
+#~ msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
+#~ msgstr "Cuando el modelo tiene pequeños huecos verticales, el tiempo de cálculo puede aumentar alrededor de un 5 % para generar el forro superior e inferior en estos espacios estrechos. En tal caso, desactive este ajuste."
+
+#~ msgctxt "build_volume_temperature description"
+#~ msgid "The temperature used for build volume. If this is 0, the build volume temperature will not be adjusted."
+#~ msgstr "La temperatura utilizada para el volumen de impresión. Si el valor es 0, la temperatura de volumen de impresión no se ajustará."
+
+#~ msgctxt "limit_support_retractions description"
+#~ msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+#~ msgstr "Omitir la retracción al moverse de soporte a soporte en línea recta. Habilitar este ajuste ahorra tiempo de impresión pero puede ocasionar un encordado excesivo en la estructura de soporte."
+
+#~ msgctxt "max_feedrate_z_override label"
+#~ msgid "Maximum Z Speed"
+#~ msgstr "Velocidad máxima de Z"
+
+#~ msgctxt "max_feedrate_z_override description"
+#~ msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
+#~ msgstr "Velocidad máxima a la que se mueve la placa de impresión. Definir este valor en 0 hace que la impresión utilice los valores predeterminados de la velocidad máxima de Z."
+
+#~ msgctxt "support_join_distance description"
+#~ msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
+#~ msgstr "Distancia máxima entre las estructuras del soporte en las direcciones X/Y. Cuando estructuras separadas están más cerca entre sí que de este valor, las estructuras se combinan en una."
+
+#~ msgctxt "support_minimal_diameter label"
+#~ msgid "Minimum Diameter"
+#~ msgstr "Diámetro mínimo"
+
+#~ msgctxt "support_minimal_diameter description"
+#~ msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+#~ msgstr "Diámetro mínimo en las direcciones X/Y de una pequeña área que soportará una torre de soporte especializada."
+
+#~ msgctxt "prime_tower_circular label"
+#~ msgid "Circular Prime Tower"
+#~ msgstr "Torre auxiliar circular"
+
+#~ msgctxt "prime_tower_circular description"
+#~ msgid "Make the prime tower as a circular shape."
+#~ msgstr "Hacer que la torre auxiliar sea circular."
+
+#~ msgctxt "prime_tower_flow description"
+#~ msgid "Flow compensation: the amount of material extruded is multiplied by this value."
+#~ msgstr "Compensación de flujo: la cantidad de material extruido se multiplica por este valor."
+
+#~ msgctxt "smooth_spiralized_contours description"
+#~ msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+#~ msgstr "Suavice los contornos espiralizados para reducir la visibilidad de la costura Z (la costura Z debería ser apenas visible en la impresora pero seguirá siendo visible en la vista de capas). Tenga en cuenta que la suavización tenderá a desdibujar detalles finos de la superficie."
+
+#~ msgctxt "support_conical_enabled description"
+#~ msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
+#~ msgstr "Función experimental: hace áreas de soporte más pequeñas en la parte inferior que en el voladizo."
+
+#~ msgctxt "extruders_enabled_count label"
+#~ msgid "Number of Extruders that are enabled"
+#~ msgstr "Número de extrusores habilitados"
+
+#~ msgctxt "machine_nozzle_tip_outer_diameter label"
+#~ msgid "Outer nozzle diameter"
+#~ msgstr "Diámetro exterior de la tobera"
+
+#~ msgctxt "machine_nozzle_head_distance label"
+#~ msgid "Nozzle length"
+#~ msgstr "Longitud de la tobera"
+
+#~ msgctxt "machine_nozzle_expansion_angle label"
+#~ msgid "Nozzle angle"
+#~ msgstr "Ángulo de la tobera"
+
+#~ msgctxt "machine_heat_zone_length label"
+#~ msgid "Heat zone length"
+#~ msgstr "Longitud de la zona térmica"
+
+#~ msgctxt "machine_nozzle_heat_up_speed label"
+#~ msgid "Heat up speed"
+#~ msgstr "Velocidad de calentamiento"
+
+#~ msgctxt "machine_nozzle_cool_down_speed label"
+#~ msgid "Cool down speed"
+#~ msgstr "Velocidad de enfriamiento"
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code flavour"
+#~ msgstr "Tipo de GCode"
+
+#~ msgctxt "machine_disallowed_areas label"
+#~ msgid "Disallowed areas"
+#~ msgstr "Áreas no permitidas"
+
+#~ msgctxt "machine_head_polygon label"
+#~ msgid "Machine head polygon"
+#~ msgstr "Polígono del cabezal de la máquina"
+
+#~ msgctxt "machine_head_with_fans_polygon label"
+#~ msgid "Machine head & Fan polygon"
+#~ msgstr "Polígono del cabezal de la máquina y del ventilador"
+
+#~ msgctxt "gantry_height label"
+#~ msgid "Gantry height"
+#~ msgstr "Altura del puente"
+
+#~ msgctxt "machine_use_extruder_offset_to_offset_coords label"
+#~ msgid "Offset With Extruder"
+#~ msgstr "Desplazamiento con extrusor"
+
+#~ msgctxt "adaptive_layer_height_enabled label"
+#~ msgid "Use adaptive layers"
+#~ msgstr "Utilizar capas de adaptación"
+
+#~ msgctxt "adaptive_layer_height_variation label"
+#~ msgid "Adaptive layers maximum variation"
+#~ msgstr "Variación máxima de las capas de adaptación"
+
+#~ msgctxt "adaptive_layer_height_variation_step label"
+#~ msgid "Adaptive layers variation step size"
+#~ msgstr "Tamaño de pasos de variación de las capas de adaptación"
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive layers threshold"
+#~ msgstr "Umbral de las capas de adaptación"
+
#~ msgctxt "skin_overlap description"
#~ msgid "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall."
#~ msgstr "La cantidad de superposición entre el forro y las paredes son un porcentaje del ancho de la línea de forro. Una ligera superposición permite que las paredes estén firmemente unidas al forro. Este es el porcentaje de la media de los anchos de las líneas del forro y la pared más profunda."
diff --git a/resources/i18n/fdmextruder.def.json.pot b/resources/i18n/fdmextruder.def.json.pot
index afec8e8257..322be35b57 100644
--- a/resources/i18n/fdmextruder.def.json.pot
+++ b/resources/i18n/fdmextruder.def.json.pot
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Uranium json setting files\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE\n"
diff --git a/resources/i18n/fdmprinter.def.json.pot b/resources/i18n/fdmprinter.def.json.pot
index 2c18d6ebed..89ff364e2d 100644
--- a/resources/i18n/fdmprinter.def.json.pot
+++ b/resources/i18n/fdmprinter.def.json.pot
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Uranium json setting files\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE\n"
@@ -218,6 +218,16 @@ msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume label"
+msgid "Has Build Volume Temperature Stabilization"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume description"
+msgid "Whether the machine is able to stabilize the build volume temperature."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
@@ -244,7 +254,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "extruders_enabled_count label"
-msgid "Number of Extruders that are enabled"
+msgid "Number of Extruders That Are Enabled"
msgstr ""
#: fdmprinter.def.json
@@ -255,7 +265,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
-msgid "Outer nozzle diameter"
+msgid "Outer Nozzle Diameter"
msgstr ""
#: fdmprinter.def.json
@@ -265,7 +275,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
+msgid "Nozzle Length"
msgstr ""
#: fdmprinter.def.json
@@ -277,7 +287,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
+msgid "Nozzle Angle"
msgstr ""
#: fdmprinter.def.json
@@ -289,7 +299,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length label"
-msgid "Heat zone length"
+msgid "Heat Zone Length"
msgstr ""
#: fdmprinter.def.json
@@ -325,7 +335,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed label"
-msgid "Heat up speed"
+msgid "Heat Up Speed"
msgstr ""
#: fdmprinter.def.json
@@ -337,7 +347,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed label"
-msgid "Cool down speed"
+msgid "Cool Down Speed"
msgstr ""
#: fdmprinter.def.json
@@ -362,7 +372,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
+msgid "G-code Flavor"
msgstr ""
#: fdmprinter.def.json
@@ -429,7 +439,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
+msgid "Disallowed Areas"
msgstr ""
#: fdmprinter.def.json
@@ -449,7 +459,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
+msgid "Machine Head Polygon"
msgstr ""
#: fdmprinter.def.json
@@ -459,7 +469,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
-msgid "Machine head & Fan polygon"
+msgid "Machine Head & Fan Polygon"
msgstr ""
#: fdmprinter.def.json
@@ -469,7 +479,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr ""
#: fdmprinter.def.json
@@ -503,7 +513,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label"
-msgid "Offset With Extruder"
+msgid "Offset with Extruder"
msgstr ""
#: fdmprinter.def.json
@@ -1111,6 +1121,18 @@ msgid ""
"value is rounded to a whole number."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers label"
+msgid "Initial Bottom Layers"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers description"
+msgid ""
+"The number of initial bottom layers, from the build-plate upwards. When "
+"calculated by the bottom thickness, this value is rounded to a whole number."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
@@ -1412,6 +1434,56 @@ msgctxt "z_seam_type option sharpest_corner"
msgid "Sharpest Corner"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "z_seam_position label"
+msgid "Z Seam Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position description"
+msgid "The position near where to start printing each part in a layer."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backleft"
+msgid "Back Left"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option back"
+msgid "Back"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backright"
+msgid "Back Right"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option right"
+msgid "Right"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontright"
+msgid "Front Right"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option front"
+msgid "Front"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontleft"
+msgid "Front Left"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option left"
+msgid "Left"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "z_seam_x label"
msgid "Z Seam X"
@@ -1448,7 +1520,9 @@ msgid ""
"seam. None means that corners have no influence on the seam position. Hide "
"Seam makes the seam more likely to occur on an inside corner. Expose Seam "
"makes the seam more likely to occur on an outside corner. Hide or Expose "
-"Seam makes the seam more likely to occur at an inside or outside corner."
+"Seam makes the seam more likely to occur at an inside or outside corner. "
+"Smart Hiding allows both inside and outside corners, but chooses inside "
+"corners more frequently, if appropriate."
msgstr ""
#: fdmprinter.def.json
@@ -1471,6 +1545,11 @@ msgctxt "z_seam_corner option z_seam_corner_any"
msgid "Hide or Expose Seam"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "z_seam_corner option z_seam_corner_weighted"
+msgid "Smart Hiding"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "z_seam_relative label"
msgid "Z Seam Relative"
@@ -1486,15 +1565,17 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic label"
-msgid "Ignore Small Z Gaps"
+msgid "No Skin in Z Gaps"
msgstr ""
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic description"
msgid ""
-"When the model has small vertical gaps, about 5% extra computation time can "
-"be spent on generating top and bottom skin in these narrow spaces. In such "
-"case, disable the setting."
+"When the model has small vertical gaps of only a few layers, there should "
+"normally be skin around those layers in the narrow space. Enable this "
+"setting to not generate skin if the vertical gap is very small. This "
+"improves printing time and slicing time, but technically leaves infill "
+"exposed to the air."
msgstr ""
#: fdmprinter.def.json
@@ -1518,9 +1599,10 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
msgid ""
-"Go over the top surface one additional time, but without extruding material. "
-"This is meant to melt the plastic on top further, creating a smoother "
-"surface."
+"Go over the top surface one additional time, but this time extruding very "
+"little material. This is meant to melt the plastic on top further, creating "
+"a smoother surface. The pressure in the nozzle chamber is kept high so that "
+"the creases in the surface are filled with material."
msgstr ""
#: fdmprinter.def.json
@@ -1621,6 +1703,39 @@ msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "skin_overlap label"
+msgid "Skin Overlap Percentage"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap description"
+msgid ""
+"Adjust the amount of overlap between the walls and (the endpoints of) the "
+"skin-centerlines, as a percentage of the line widths of the skin lines and "
+"the innermost wall. A slight overlap allows the walls to connect firmly to "
+"the skin. Note that, given an equal skin and wall line-width, any percentage "
+"over 50% may already cause any skin to go past the wall, because at that "
+"point the position of the nozzle of the skin-extruder may already reach past "
+"the middle of the wall."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm label"
+msgid "Skin Overlap"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm description"
+msgid ""
+"Adjust the amount of overlap between the walls and (the endpoints of) the "
+"skin-centerlines. A slight overlap allows the walls to connect firmly to the "
+"skin. Note that, given an equal skin and wall line-width, any value over "
+"half the width of the wall may already cause any skin to go past the wall, "
+"because at that point the position of the nozzle of the skin-extruder may "
+"already reach past the middle of the wall."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "infill label"
msgid "Infill"
@@ -1809,6 +1924,19 @@ msgctxt "infill_offset_y description"
msgid "The infill pattern is moved this distance along the Y axis."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location label"
+msgid "Randomize Infill Start"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location description"
+msgid ""
+"Randomize which infill line is printed first. This prevents one segment "
+"becoming the strongest, but it does so at the cost of an additional travel "
+"move."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "infill_multiplier label"
msgid "Infill Line Multiplier"
@@ -1877,39 +2005,6 @@ msgid ""
"allows the walls to connect firmly to the infill."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "skin_overlap label"
-msgid "Skin Overlap Percentage"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap description"
-msgid ""
-"Adjust the amount of overlap between the walls and (the endpoints of) the "
-"skin-centerlines, as a percentage of the line widths of the skin lines and "
-"the innermost wall. A slight overlap allows the walls to connect firmly to "
-"the skin. Note that, given an equal skin and wall line-width, any percentage "
-"over 50% may already cause any skin to go past the wall, because at that "
-"point the position of the nozzle of the skin-extruder may already reach past "
-"the middle of the wall."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm label"
-msgid "Skin Overlap"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm description"
-msgid ""
-"Adjust the amount of overlap between the walls and (the endpoints of) the "
-"skin-centerlines. A slight overlap allows the walls to connect firmly to the "
-"skin. Note that, given an equal skin and wall line-width, any value over "
-"half the width of the wall may already cause any skin to go past the wall, "
-"because at that point the position of the nozzle of the skin-extruder may "
-"already reach past the middle of the wall."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "infill_wipe_dist label"
msgid "Infill Wipe Distance"
@@ -2143,6 +2238,18 @@ msgid ""
"based on this value"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature label"
+msgid "Build Volume Temperature"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature description"
+msgid ""
+"The temperature of the environment to print in. If this is 0, the build "
+"volume temperature will not be adjusted."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
msgid "Printing Temperature"
@@ -2266,6 +2373,94 @@ msgctxt "material_shrinkage_percentage description"
msgid "Shrinkage ratio in percentage."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "material_crystallinity label"
+msgid "Crystalline Material"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_crystallinity description"
+msgid ""
+"Is this material the type that breaks off cleanly when heated (crystalline), "
+"or is it the type that produces long intertwined polymer chains (non-"
+"crystalline)?"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position label"
+msgid "Anti-ooze Retracted Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position description"
+msgid "How far the material needs to be retracted before it stops oozing."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed label"
+msgid "Anti-ooze Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed description"
+msgid ""
+"How fast the material needs to be retracted during a filament switch to "
+"prevent oozing."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position label"
+msgid "Break Preparation Retracted Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position description"
+msgid "How far the filament can be stretched before it breaks, while heated."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed label"
+msgid "Break Preparation Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed description"
+msgid ""
+"How fast the filament needs to be retracted just before breaking it off in a "
+"retraction."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position label"
+msgid "Break Retracted Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position description"
+msgid "How far to retract the filament in order to break it cleanly."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed label"
+msgid "Break Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed description"
+msgid ""
+"The speed at which to retract the filament in order to break it cleanly."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature label"
+msgid "Break Temperature"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature description"
+msgid "The temperature at which the filament is broken for a clean break."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "material_flow label"
msgid "Flow"
@@ -2278,6 +2473,127 @@ msgid ""
"value."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "wall_material_flow label"
+msgid "Wall Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_material_flow description"
+msgid "Flow compensation on wall lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow label"
+msgid "Outer Wall Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow description"
+msgid "Flow compensation on the outermost wall line."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow label"
+msgid "Inner Wall(s) Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow description"
+msgid ""
+"Flow compensation on wall lines for all wall lines except the outermost one."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow label"
+msgid "Top/Bottom Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow description"
+msgid "Flow compensation on top/bottom lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow label"
+msgid "Top Surface Skin Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow description"
+msgid "Flow compensation on lines of the areas at the top of the print."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow label"
+msgid "Infill Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow description"
+msgid "Flow compensation on infill lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow label"
+msgid "Skirt/Brim Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow description"
+msgid "Flow compensation on skirt or brim lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow label"
+msgid "Support Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow description"
+msgid "Flow compensation on support structure lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow label"
+msgid "Support Interface Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow description"
+msgid "Flow compensation on lines of support roof or floor."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow label"
+msgid "Support Roof Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow description"
+msgid "Flow compensation on support roof lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow label"
+msgid "Support Floor Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow description"
+msgid "Flow compensation on support floor lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow label"
+msgid "Prime Tower Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow description"
+msgid "Flow compensation on prime tower lines."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "material_flow_layer_0 label"
msgid "Initial Layer Flow"
@@ -2414,7 +2730,7 @@ msgstr ""
msgctxt "limit_support_retractions description"
msgid ""
"Omit retraction when moving from support to support in a straight line. "
-"Enabling this setting saves print time, but can lead to excesive stringing "
+"Enabling this setting saves print time, but can lead to excessive stringing "
"within the support structure."
msgstr ""
@@ -2478,6 +2794,16 @@ msgid ""
"retraction."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount label"
+msgid "Nozzle Switch Extra Prime Amount"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount description"
+msgid "Extra material to prime after nozzle switching."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "speed label"
msgid "Speed"
@@ -2701,15 +3027,16 @@ msgid ""
msgstr ""
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override label"
-msgid "Maximum Z Speed"
+msgctxt "speed_z_hop label"
+msgid "Z Hop Speed"
msgstr ""
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override description"
+msgctxt "speed_z_hop description"
msgid ""
-"The maximum speed with which the build plate is moved. Setting this to zero "
-"causes the print to use the firmware defaults for the maximum z speed."
+"The speed at which the vertical Z movement is made for Z Hops. This is "
+"typically lower than the print speed since the build plate or machine's "
+"gantry is harder to move."
msgstr ""
#: fdmprinter.def.json
@@ -3273,20 +3600,6 @@ msgid ""
"during travel moves."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position label"
-msgid "Start Layers with the Same Part"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position description"
-msgid ""
-"In each layer start with printing the object near the same point, so that we "
-"don't start a new layer with printing the piece which the previous layer "
-"ended with. This makes for better overhangs and small parts, but increases "
-"printing time."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
@@ -3360,6 +3673,16 @@ msgid ""
"prevents the nozzle from leaving oozed material on the outside of a print."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height label"
+msgid "Z Hop After Extruder Switch Height"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height description"
+msgid "The height difference when performing a Z Hop after extruder switch."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "cooling label"
msgid "Cooling"
@@ -3682,6 +4005,11 @@ msgctxt "support_pattern option cross"
msgid "Cross"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "support_pattern option gyroid"
+msgid "Gyroid"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_wall_count label"
msgid "Support Wall Line Count"
@@ -3757,15 +4085,18 @@ msgid ""
msgstr ""
#: fdmprinter.def.json
-msgctxt "support_infill_angle label"
-msgid "Support Infill Line Direction"
+msgctxt "support_infill_angles label"
+msgid "Support Infill Line Directions"
msgstr ""
#: fdmprinter.def.json
-msgctxt "support_infill_angle description"
+msgctxt "support_infill_angles description"
msgid ""
-"Orientation of the infill pattern for supports. The support infill pattern "
-"is rotated in the horizontal plane."
+"A list of integer line directions to use. Elements from the list are used "
+"sequentially as the layers progress and when the end of the list is reached, "
+"it starts at the beginning again. The list items are separated by commas and "
+"the whole list is contained in square brackets. Default is an empty list "
+"which means use the default angle 0 degrees."
msgstr ""
#: fdmprinter.def.json
@@ -3919,7 +4250,7 @@ msgstr ""
msgctxt "support_join_distance description"
msgid ""
"The maximum distance between support structures in the X/Y directions. When "
-"seperate structures are closer together than this value, the structures "
+"separate structures are closer together than this value, the structures "
"merge into one."
msgstr ""
@@ -4248,7 +4579,7 @@ msgstr ""
msgctxt "minimum_interface_area description"
msgid ""
"Minimum area size for support interface polygons. Polygons which have an "
-"area smaller than this value will not be generated."
+"area smaller than this value will be printed as normal support."
msgstr ""
#: fdmprinter.def.json
@@ -4260,7 +4591,7 @@ msgstr ""
msgctxt "minimum_roof_area description"
msgid ""
"Minimum area size for the roofs of the support. Polygons which have an area "
-"smaller than this value will not be generated."
+"smaller than this value will be printed as normal support."
msgstr ""
#: fdmprinter.def.json
@@ -4272,7 +4603,7 @@ msgstr ""
msgctxt "minimum_bottom_area description"
msgid ""
"Minimum area size for the floors of the support. Polygons which have an area "
-"smaller than this value will not be generated."
+"smaller than this value will be printed as normal support."
msgstr ""
#: fdmprinter.def.json
@@ -4305,6 +4636,54 @@ msgctxt "support_bottom_offset description"
msgid "Amount of offset applied to the floors of the support."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "support_interface_angles label"
+msgid "Support Interface Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles description"
+msgid ""
+"A list of integer line directions to use. Elements from the list are used "
+"sequentially as the layers progress and when the end of the list is reached, "
+"it starts at the beginning again. The list items are separated by commas and "
+"the whole list is contained in square brackets. Default is an empty list "
+"which means use the default angles (alternates between 45 and 135 degrees if "
+"interfaces are quite thick or 90 degrees)."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles label"
+msgid "Support Roof Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles description"
+msgid ""
+"A list of integer line directions to use. Elements from the list are used "
+"sequentially as the layers progress and when the end of the list is reached, "
+"it starts at the beginning again. The list items are separated by commas and "
+"the whole list is contained in square brackets. Default is an empty list "
+"which means use the default angles (alternates between 45 and 135 degrees if "
+"interfaces are quite thick or 90 degrees)."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles label"
+msgid "Support Floor Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles description"
+msgid ""
+"A list of integer line directions to use. Elements from the list are used "
+"sequentially as the layers progress and when the end of the list is reached, "
+"it starts at the beginning again. The list items are separated by commas and "
+"the whole list is contained in square brackets. Default is an empty list "
+"which means use the default angles (alternates between 45 and 135 degrees if "
+"interfaces are quite thick or 90 degrees)."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -4353,14 +4732,14 @@ msgid "The diameter of a special tower."
msgstr ""
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter label"
-msgid "Minimum Diameter"
+msgctxt "support_tower_maximum_supported_diameter label"
+msgid "Maximum Tower-Supported Diameter"
msgstr ""
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter description"
+msgctxt "support_tower_maximum_supported_diameter description"
msgid ""
-"Minimum diameter in the X/Y directions of a small area which is to be "
+"Maximum diameter in the X/Y directions of a small area which is to be "
"supported by a specialized support tower."
msgstr ""
@@ -4935,16 +5314,6 @@ msgid ""
"each nozzle switch."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular label"
-msgid "Circular Prime Tower"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular description"
-msgid "Make the prime tower as a circular shape."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
@@ -4987,18 +5356,6 @@ msgctxt "prime_tower_position_y description"
msgid "The y coordinate of the position of the prime tower."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow label"
-msgid "Prime Tower Flow"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow description"
-msgid ""
-"Flow compensation: the amount of material extruded is multiplied by this "
-"value."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
@@ -5011,6 +5368,18 @@ msgid ""
"the other nozzle off on the prime tower."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable label"
+msgid "Prime Tower Brim"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable description"
+msgid ""
+"Prime-towers might need the extra adhesion afforded by a brim even if the "
+"model doesn't. Presently can't be used with the 'Raft' adhesion-type."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
msgid "Enable Ooze Shield"
@@ -5161,6 +5530,49 @@ msgid ""
"setting is set to Exclusive or Middle."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid ""
+"The minimum size of a line segment after slicing. If you increase this, the "
+"mesh will have a lower resolution. This may allow the printer to keep up "
+"with the speed it has to process g-code and will increase slice speed by "
+"removing details of the mesh that it can't process anyway."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution label"
+msgid "Maximum Travel Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution description"
+msgid ""
+"The minimum size of a travel line segment after slicing. If you increase "
+"this, the travel moves will have less smooth corners. This may allow the "
+"printer to keep up with the speed it has to process g-code, but it may cause "
+"model avoidance to become less accurate."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation label"
+msgid "Maximum Deviation"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation description"
+msgid ""
+"The maximum deviation allowed when reducing the resolution for the Maximum "
+"Resolution setting. If you increase this, the print will be less accurate, "
+"but the g-code will be smaller. Maximum Deviation is a limit for Maximum "
+"Resolution, so if the two conflict the Maximum Deviation will always be held "
+"true."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "blackmagic label"
msgid "Special Modes"
@@ -5358,7 +5770,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "smooth_spiralized_contours description"
msgid ""
-"Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-"
+"Smooth the spiralized contours to reduce the visibility of the Z seam (the Z "
"seam should be barely visible on the print but will still be visible in the "
"layer view). Note that smoothing will tend to blur fine surface details."
msgstr ""
@@ -5625,34 +6037,6 @@ msgid ""
"and very tiny 3D models with a lot of details."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid ""
-"The minimum size of a line segment after slicing. If you increase this, the "
-"mesh will have a lower resolution. This may allow the printer to keep up "
-"with the speed it has to process g-code and will increase slice speed by "
-"removing details of the mesh that it can't process anyway."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution label"
-msgid "Maximum Travel Resolution"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution description"
-msgid ""
-"The minimum size of a travel line segment after slicing. If you increase "
-"this, the travel moves will have less smooth corners. This may allow the "
-"printer to keep up with the speed it has to process g-code, but it may cause "
-"model avoidance to become less accurate."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5823,19 +6207,6 @@ msgid ""
"coasting move the pressure in the bowden tube drops."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation label"
-msgid "Alternate Skin Rotation"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation description"
-msgid ""
-"Alternate the direction in which the top/bottom layers are printed. Normally "
-"they are printed diagonally only. This setting adds the X-only and Y-only "
-"directions."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "cross_infill_pocket_size label"
msgid "Cross 3D Pocket Size"
@@ -5965,9 +6336,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "support_conical_enabled description"
-msgid ""
-"Experimental feature: Make support areas smaller at the bottom than at the "
-"overhang."
+msgid "Make support areas smaller at the bottom than at the overhang."
msgstr ""
#: fdmprinter.def.json
@@ -6049,22 +6418,27 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
-msgid "Flow rate compensation max extrusion offset"
+msgid "Flow Rate Compensation Max Extrusion Offset"
msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
-msgid "The maximum distance in mm to compensate."
+msgid ""
+"The maximum distance in mm to move the filament to compensate for changes in "
+"flow rate."
msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor label"
-msgid "Flow rate compensation factor"
+msgid "Flow Rate Compensation Factor"
msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor description"
-msgid "The multiplication factor for the flow rate -> distance translation."
+msgid ""
+"How far to move the filament in order to compensate for changes in flow "
+"rate, as a percentage of how far the filament would move in one second of "
+"extrusion."
msgstr ""
#: fdmprinter.def.json
@@ -6382,7 +6756,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr ""
#: fdmprinter.def.json
@@ -6394,7 +6768,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation label"
-msgid "Adaptive layers maximum variation"
+msgid "Adaptive Layers Maximum Variation"
msgstr ""
#: fdmprinter.def.json
@@ -6404,7 +6778,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation_step label"
-msgid "Adaptive layers variation step size"
+msgid "Adaptive Layers Variation Step Size"
msgstr ""
#: fdmprinter.def.json
@@ -6416,14 +6790,15 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
+msgid "Adaptive Layers Topography Size"
msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold description"
msgid ""
-"Threshold whether to use a smaller layer or not. This number is compared to "
-"the tan of the steepest slope in a layer."
+"Target horizontal distance between two adjacent layers. Reducing this "
+"setting causes thinner layers to be used to bring the edges of the layers "
+"closer together."
msgstr ""
#: fdmprinter.def.json
@@ -6435,7 +6810,9 @@ msgstr ""
msgctxt "wall_overhang_angle description"
msgid ""
"Walls that overhang more than this angle will be printed using overhanging "
-"wall settings. When the value is 90, no walls will be treated as overhanging."
+"wall settings. When the value is 90, no walls will be treated as "
+"overhanging. Overhang that gets supported by support will not be treated as "
+"overhang either."
msgstr ""
#: fdmprinter.def.json
@@ -6668,6 +7045,222 @@ msgctxt "bridge_fan_speed_3 description"
msgid "Percentage fan speed to use when printing the third bridge skin layer."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "clean_between_layers label"
+msgid "Wipe Nozzle Between Layers"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "clean_between_layers description"
+msgid ""
+"Whether to include nozzle wipe G-Code between layers. Enabling this setting "
+"could influence behavior of retract at layer change. Please use Wipe "
+"Retraction settings to control retraction at layers where the wipe script "
+"will be working."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe label"
+msgid "Material Volume Between Wipes"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe description"
+msgid ""
+"Maximum material, that can be extruded before another nozzle wipe is "
+"initiated."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable label"
+msgid "Wipe Retraction Enable"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable description"
+msgid "Retract the filament when the nozzle is moving over a non-printed area."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount label"
+msgid "Wipe Retraction Distance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount description"
+msgid ""
+"Amount to retract the filament so it does not ooze during the wipe sequence."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount label"
+msgid "Wipe Retraction Extra Prime Amount"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount description"
+msgid ""
+"Some material can ooze away during a wipe travel moves, which can be "
+"compensated for here."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed label"
+msgid "Wipe Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed description"
+msgid ""
+"The speed at which the filament is retracted and primed during a wipe "
+"retraction move."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed label"
+msgid "Wipe Retraction Retract Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed description"
+msgid ""
+"The speed at which the filament is retracted during a wipe retraction move."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed label"
+msgid "Retraction Prime Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed description"
+msgid ""
+"The speed at which the filament is primed during a wipe retraction move."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause label"
+msgid "Wipe Pause"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause description"
+msgid "Pause after the unretract."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable label"
+msgid "Wipe Z Hop When Retracted"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable description"
+msgid ""
+"Whenever a retraction is done, the build plate is lowered to create "
+"clearance between the nozzle and the print. It prevents the nozzle from "
+"hitting the print during travel moves, reducing the chance to knock the "
+"print from the build plate."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount label"
+msgid "Wipe Z Hop Height"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount description"
+msgid "The height difference when performing a Z Hop."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed label"
+msgid "Wipe Hop Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed description"
+msgid "Speed to move the z-axis during the hop."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x label"
+msgid "Wipe Brush X Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x description"
+msgid "X location where wipe script will start."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count label"
+msgid "Wipe Repeat Count"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count description"
+msgid "Number of times to move the nozzle across the brush."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance label"
+msgid "Wipe Move Distance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance description"
+msgid "The distance to move the head back and forth across the brush."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size label"
+msgid "Small Hole Max Size"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size description"
+msgid ""
+"Holes and part outlines with a diameter smaller than this will be printed "
+"using Small Feature Speed."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length label"
+msgid "Small Feature Max Length"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length description"
+msgid ""
+"Feature outlines that are shorter than this length will be printed using "
+"Small Feature Speed."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor label"
+msgid "Small Feature Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor description"
+msgid ""
+"Small features will be printed at this percentage of their normal print "
+"speed. Slower printing can help with adhesion and accuracy."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 label"
+msgid "Small Feature Initial Layer Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 description"
+msgid ""
+"Small features on the first layer will be printed at this percentage of "
+"their normal print speed. Slower printing can help with adhesion and "
+"accuracy."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
diff --git a/resources/i18n/fi_FI/cura.po b/resources/i18n/fi_FI/cura.po
index d07b032bad..bfc110737f 100644
--- a/resources/i18n/fi_FI/cura.po
+++ b/resources/i18n/fi_FI/cura.po
@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
"PO-Revision-Date: 2017-09-27 12:27+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr "Laitteen asetukset"
@@ -38,13 +38,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr "GCode-tiedosto"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr ""
@@ -54,7 +54,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -64,70 +64,49 @@ msgid ""
"
"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Changelog"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
-msgstr "Näytä muutosloki"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
msgctxt "@action"
msgid "Update Firmware"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
-msgctxt "@item:inmenu"
-msgid "Flatten active settings"
-msgstr "Aktivoitujen asetusten tasoitus"
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:35
-msgctxt "@info:status"
-msgid "Profile has been flattened & activated."
-msgstr "Profiili on tasoitettu ja aktivoitu."
-
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:33
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "USB-tulostus"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:34
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:43
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Tulosta USB:n kautta"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:35
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:44
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Tulosta USB:n kautta"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:71
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:80
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Yhdistetty USB:n kautta"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:96
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:105
msgctxt "@label"
msgid "A USB print is in progress, closing Cura will stop this print. Are you sure?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/install/X3GWriter/__init__.py:15
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
-msgctxt "X3G Writer File Description"
-msgid "X3G File"
-msgstr "X3G-tiedosto"
-
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
-msgctxt "X3g Writer Plugin Description"
-msgid "Writes X3g to files"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "A print is still in progress. Cura cannot start another print via USB until the previous print has completed."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:21
-msgctxt "X3g Writer File Description"
-msgid "X3g File"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "Print in Progress"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
@@ -142,6 +121,7 @@ msgid "GCodeGzWriter does not support text mode."
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:28
+#: /home/ruben/Projects/Cura/plugins/UFPReader/__init__.py:22
msgctxt "@item:inlistbox"
msgid "Ultimaker Format Package"
msgstr ""
@@ -163,7 +143,7 @@ msgid "Save to Removable Drive {0}"
msgstr "Tallenna siirrettävälle asemalle {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:107
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr ""
@@ -200,10 +180,9 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "Ei voitu tallentaa siirrettävälle asemalle {0}: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:152
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1629
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:139
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1668
msgctxt "@info:title"
msgid "Error"
msgstr "Virhe"
@@ -232,9 +211,9 @@ msgstr "Poista siirrettävä asema {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:151
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:163
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1619
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1719
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1658
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1758
msgctxt "@info:title"
msgid "Warning"
msgstr "Varoitus"
@@ -261,337 +240,164 @@ msgctxt "@item:intext"
msgid "Removable Drive"
msgstr "Siirrettävä asema"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:74
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py:26
+msgctxt "@action"
+msgid "Connect via Network"
+msgstr "Yhdistä verkon kautta"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:57
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Tulosta verkon kautta"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:58
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Tulosta verkon kautta"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
-msgctxt "@info:status"
-msgid "Connected over the network."
-msgstr "Yhdistetty verkon kautta tulostimeen."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
-msgctxt "@info:status"
-msgid "Connected over the network. Please approve the access request on the printer."
-msgstr "Yhdistetty verkon kautta. Hyväksy tulostimen käyttöoikeuspyyntö."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:93
-msgctxt "@info:status"
-msgid "Connected over the network. No access to control the printer."
-msgstr "Yhdistetty verkon kautta tulostimeen. Ei käyttöoikeutta tulostimen hallintaan."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
-msgctxt "@info:status"
-msgid "Access to the printer requested. Please approve the request on the printer"
-msgstr "Tulostimen käyttöoikeutta pyydetty. Hyväksy tulostimen pyyntö"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:101
-msgctxt "@info:title"
-msgid "Authentication status"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
-msgctxt "@info:title"
-msgid "Authentication Status"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:187
-msgctxt "@action:button"
-msgid "Retry"
-msgstr "Yritä uudelleen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
-msgctxt "@info:tooltip"
-msgid "Re-send the access request"
-msgstr "Lähetä käyttöoikeuspyyntö uudelleen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
-msgctxt "@info:status"
-msgid "Access to the printer accepted"
-msgstr "Tulostimen käyttöoikeus hyväksytty"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
-msgctxt "@info:status"
-msgid "No access to print with this printer. Unable to send print job."
-msgstr "Tällä tulostimella tulostukseen ei ole käyttöoikeutta. Tulostustyön lähetys ei onnistu."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:65
-msgctxt "@action:button"
-msgid "Request Access"
-msgstr "Pyydä käyttöoikeutta"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:66
-msgctxt "@info:tooltip"
-msgid "Send access request to the printer"
-msgstr "Lähetä tulostimen käyttöoikeuspyyntö"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:201
-msgctxt "@label"
-msgid "Unable to start a new print job."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:203
-msgctxt "@label"
-msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:209
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:231
-msgctxt "@window:title"
-msgid "Mismatched configuration"
-msgstr "Ristiriitainen määritys"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:223
-msgctxt "@label"
-msgid "Are you sure you wish to print with the selected configuration?"
-msgstr "Haluatko varmasti tulostaa valitulla määrityksellä?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:225
-msgctxt "@label"
-msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Tulostimen ja Curan määrityksen tai kalibroinnin välillä on ristiriita. Parhaat tulokset saavutetaan viipaloimalla aina tulostimeen asetetuille PrintCoreille ja materiaaleille."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:252
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:162
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:162
-msgctxt "@info:status"
-msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
-msgstr "Uusien töiden lähettäminen (tilapäisesti) estetty, edellistä tulostustyötä lähetetään vielä."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:180
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
-msgctxt "@info:status"
-msgid "Sending data to printer"
-msgstr "Lähetetään tietoja tulostimeen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:182
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:199
-msgctxt "@info:title"
-msgid "Sending Data"
-msgstr "Lähetetään tietoja"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:200
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:395
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:38
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:391
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:254
-msgctxt "@action:button"
-msgid "Cancel"
-msgstr "Peruuta"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:324
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:330
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No material loaded in slot {slot_number}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:353
-#, python-brace-format
-msgctxt "@label"
-msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:362
-#, python-brace-format
-msgctxt "@label"
-msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr "Eri materiaali (Cura: {0}, tulostin: {1}) valittu suulakkeelle {2}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:548
-msgctxt "@window:title"
-msgid "Sync with your printer"
-msgstr "Synkronoi tulostimen kanssa"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:550
-msgctxt "@label"
-msgid "Would you like to use your current printer configuration in Cura?"
-msgstr "Haluatko käyttää nykyistä tulostimen määritystä Curassa?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:552
-msgctxt "@label"
-msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Tulostimen PrintCoret tai materiaalit eivät vastaa tulostettavan projektin asetuksia. Parhaat tulokset saavutetaan viipaloimalla aina tulostimeen asetetuille PrintCoreille ja materiaaleille."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:59
msgctxt "@info:status"
msgid "Connected over the network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:275
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:342
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:15
msgctxt "@info:status"
-msgid "Print job was successfully sent to the printer."
+msgid "Please wait until the current job has been sent."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:277
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:343
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:16
msgctxt "@info:title"
-msgid "Data Sent"
+msgid "Print error"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:278
-msgctxt "@action:button"
-msgid "View in Monitor"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:21
+msgctxt "@info:title"
+msgid "New cloud printers found"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:390
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:290
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:22
+msgctxt "@info:message"
+msgid "New printers have been found connected to your account, you can find them in your list of discovered printers."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:27
+msgctxt "@info:option_text"
+msgid "Do not show this message again"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:27
#, python-brace-format
msgctxt "@info:status"
-msgid "Printer '{printer_name}' has finished printing '{job_name}'."
-msgstr "{printer_name} on tulostanut työn '{job_name}'."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:392
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:294
-#, python-brace-format
-msgctxt "@info:status"
-msgid "The print job '{job_name}' was finished."
+msgid "You are attempting to connect to {0} but it is not the host of a group. You can visit the web page to configure it as a group host."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:393
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:289
-msgctxt "@info:status"
-msgid "Print finished"
-msgstr "Tulosta valmis"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:573
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:607
-msgctxt "@label:material"
-msgid "Empty"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:574
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:608
-msgctxt "@label:material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:151
-msgctxt "@action:button"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:152
-msgctxt "@properties:tooltip"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:153
-msgctxt "@info:status"
-msgid "Connected via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:163
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:30
msgctxt "@info:title"
-msgid "Cloud error"
+msgid "Not a group host"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:180
-msgctxt "@info:status"
-msgid "Could not export print job."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:35
+msgctxt "@action"
+msgid "Configure group"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:330
-msgctxt "@info:text"
-msgid "Could not upload the data to the printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
-msgctxt "@info:status"
-msgid "tomorrow"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
-msgctxt "@info:status"
-msgid "today"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:151
-msgctxt "@info:description"
-msgid "There was an error connecting to the cloud."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
-msgctxt "@info:status"
-msgid "Sending data to remote cluster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:456
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:27
msgctxt "@info:status"
msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:460
-msgctxt "@info:status"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:33
+msgctxt "@info:status Ultimaker Cloud should not be translated."
msgid "Connect to Ultimaker Cloud"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:461
-msgctxt "@action"
-msgid "Don't ask me again for this printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:464
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:36
msgctxt "@action"
msgid "Get started"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:478
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:14
msgctxt "@info:status"
-msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
+msgid "Sending Print Job"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:482
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:15
msgctxt "@info:status"
-msgid "Connected!"
+msgid "Uploading print job to printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:486
-msgctxt "@action"
-msgid "Review your connection"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:15
+msgctxt "@info:status"
+msgid "Print job was successfully sent to the printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
-msgctxt "@action"
-msgid "Connect via Network"
-msgstr "Yhdistä verkon kautta"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:16
+msgctxt "@info:title"
+msgid "Data Sent"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:18
+msgctxt "@info:status"
+msgid "You are attempting to connect to a printer that is not running Ultimaker Connect. Please update the printer to the latest firmware."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:21
+msgctxt "@info:title"
+msgid "Update your printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:24
+#, python-brace-format
+msgctxt "@info:status"
+msgid "Cura has detected material profiles that were not yet installed on the host printer of group {0}."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:26
+msgctxt "@info:title"
+msgid "Sending materials to printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:15
+msgctxt "@info:text"
+msgid "Could not upload the data to the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:16
+msgctxt "@info:title"
+msgid "Network error"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:27
+msgctxt "@info:status"
+msgid "tomorrow"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:30
+msgctxt "@info:status"
+msgid "today"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:138
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:139
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:140
+msgctxt "@info:status"
+msgid "Connected via Cloud"
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:124
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:125
msgctxt "@info"
msgid "Could not access update information."
msgstr "Päivitystietoja ei löytynyt."
@@ -618,12 +424,12 @@ msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Kerrosnäkymä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:117
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Cura ei näytä kerroksia täsmällisesti, kun rautalankatulostus on käytössä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:118
msgctxt "@info:title"
msgid "Simulation View"
msgstr ""
@@ -648,46 +454,11 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:55
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Kerätään tietoja"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:57
-msgctxt "@action:button"
-msgid "More info"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:58
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:60
-msgctxt "@action:button"
-msgid "Allow"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:61
-msgctxt "@action:tooltip"
-msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Cura 15.04 -profiilit"
-#: /home/ruben/Projects/Cura/plugins/R2D2/__init__.py:17
-msgctxt "@item:inmenu"
-msgid "Evaluation"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/ImageReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "JPG Image"
@@ -713,56 +484,86 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "GIF-kuva"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:15
+msgctxt "@item:inlistbox 'Open' is part of the name of this file format."
+msgid "Open Compressed Triangle Mesh"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:19
+msgctxt "@item:inlistbox"
+msgid "COLLADA Digital Asset Exchange"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:23
+msgctxt "@item:inlistbox"
+msgid "glTF Binary"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:27
+msgctxt "@item:inlistbox"
+msgid "glTF Embedded JSON"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:36
+msgctxt "@item:inlistbox"
+msgid "Stanford Triangle Format"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:40
+msgctxt "@item:inlistbox"
+msgid "Compressed COLLADA Digital Asset Exchange"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
msgctxt "@info:status"
msgid "Unable to slice with the current material as it is incompatible with the selected machine or configuration."
msgstr "Viipalointi ei onnistu nykyisellä materiaalilla, sillä se ei sovellu käytettäväksi valitun laitteen tai kokoonpanon kanssa."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:389
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:398
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:407
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:416
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:362
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:386
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:395
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:404
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:413
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "Viipalointi ei onnistu"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "Viipalointi ei onnistu nykyisten asetuksien ollessa voimassa. Seuraavissa asetuksissa on virheitä: {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:394
msgctxt "@info:status"
msgid "Unable to slice because the prime tower or prime position(s) are invalid."
msgstr "Viipalointi ei onnistu, koska esitäyttötorni tai esitäytön sijainti tai sijainnit eivät kelpaa."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid "Unable to slice because there are objects associated with disabled Extruder %s."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:412
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume or are assigned to a disabled extruder. Please scale or rotate models to fit, or enable an extruder."
msgstr ""
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Käsitellään kerroksia"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Tiedot"
@@ -777,12 +578,12 @@ msgctxt "@info:tooltip"
msgid "Configure Per Model Settings"
msgstr "Määritä mallikohtaiset asetukset"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:186
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Suositeltu"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:188
msgctxt "@title:tab"
msgid "Custom"
msgstr "Mukautettu"
@@ -793,19 +594,19 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "3MF-tiedosto"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:190
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:763
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:198
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:651
msgctxt "@label"
msgid "Nozzle"
msgstr "Suutin"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:469
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:496
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Project file {0} contains an unknown machine type {1}. Cannot import the machine. Models will be imported instead."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:472
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:499
msgctxt "@info:title"
msgid "Open Project File"
msgstr ""
@@ -820,18 +621,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "G File -tiedosto"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:324
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:335
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "G-coden jäsennys"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:326
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:476
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:337
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:491
msgctxt "@info:title"
msgid "G-code Details"
msgstr "G-coden tiedot"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:474
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:489
msgctxt "@info:generic"
msgid "Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."
msgstr "Varmista, että G-code on tulostimelle ja sen tulostusasetuksille soveltuva, ennen kuin lähetät tiedoston siihen. G-coden esitys ei välttämättä ole tarkka."
@@ -854,7 +655,7 @@ msgctxt "@info:backup_status"
msgid "There was an error listing your backups."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:121
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:132
msgctxt "@info:backup_status"
msgid "There was an error trying to restore your backup."
msgstr ""
@@ -885,16 +686,6 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Cura-profiili"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
-msgctxt "@item:inmenu"
-msgid "Profile Assistant"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
-msgctxt "@item:inlistbox"
-msgid "Profile Assistant"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:26
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -915,272 +706,361 @@ msgctxt "@item:inmenu"
msgid "Preview"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Valitse päivitykset"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
-msgctxt "@action"
-msgid "Checkup"
-msgstr "Tarkastus"
-
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
msgstr "Tasaa alusta"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:81
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Ulkoseinämä"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:82
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Sisäseinämät"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:83
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Pintakalvo"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:84
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Täyttö"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:85
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Tuen täyttö"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:86
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Tukiliittymä"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:87
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Tuki"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:88
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Helma"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Siirtoliike"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Takaisinvedot"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Muu"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:309
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Esiviipaloitu tiedosto {0}"
-
-#: /home/ruben/Projects/Cura/cura/API/Account.py:77
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
msgctxt "@info:title"
msgid "Login failed"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:201
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:36
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:55
+msgctxt "@info:No intent profile selected"
+msgid "Default"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:196
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:125
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Tiedosto on jo olemassa"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:202
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:197
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:126
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Tiedosto {0} on jo olemassa. Haluatko varmasti kirjoittaa sen päälle?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:425
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:428
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:433
msgctxt "@info:status"
msgid "Invalid file URL:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:206
-msgctxt "@menuitem"
-msgid "Not overridden"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:780
+msgctxt "@info:message Followed by a list of settings."
+msgid "Settings have been changed to match the current availability of extruders:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:915
-#, python-format
-msgctxt "@info:generic"
-msgid "Settings have been changed to match the current availability of extruders: [%s]"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:917
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:782
msgctxt "@info:title"
msgid "Settings updated"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1458
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1334
msgctxt "@info:title"
msgid "Extruder(s) Disabled"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1457
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:99
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:86
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:182
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:223
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Tuntematon"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:137
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "Profiilin vienti epäonnistui tiedostoon {0}: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:138
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "Profiilin vienti epäonnistui tiedostoon {0}: Kirjoitin-lisäosa ilmoitti virheestä."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:149
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "Profiili viety tiedostoon {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:150
msgctxt "@info:title"
msgid "Export succeeded"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr ""
-
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
+msgid "Failed to import profile from {0}: {1}"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:181
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags !"
msgid "Can't import profile from {0} before a printer is added."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:198
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "No custom profile to import in file {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:202
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:226
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:236
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "This profile {0} contains incorrect data, could not import it."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:241
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:325
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to import profile from {0}:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:328
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Onnistuneesti tuotu profiili {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:319
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:331
#, python-brace-format
msgctxt "@info:status"
msgid "File {0} does not contain any valid profile."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:322
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:334
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "Profiililla {0} on tuntematon tiedostotyyppi tai se on vioittunut."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:340
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:369
msgctxt "@label"
msgid "Custom profile"
msgstr "Mukautettu profiili"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:385
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "Profiilista puuttuu laatutyyppi."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:370
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:399
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "Laatutyyppiä {0} ei löydy nykyiselle kokoonpanolle."
-#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:69
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:76
+msgctxt "@tooltip"
+msgid "Outer Wall"
+msgstr "Ulkoseinämä"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:77
+msgctxt "@tooltip"
+msgid "Inner Walls"
+msgstr "Sisäseinämät"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:78
+msgctxt "@tooltip"
+msgid "Skin"
+msgstr "Pintakalvo"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:79
+msgctxt "@tooltip"
+msgid "Infill"
+msgstr "Täyttö"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:80
+msgctxt "@tooltip"
+msgid "Support Infill"
+msgstr "Tuen täyttö"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:81
+msgctxt "@tooltip"
+msgid "Support Interface"
+msgstr "Tukiliittymä"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:82
+msgctxt "@tooltip"
+msgid "Support"
+msgstr "Tuki"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:83
+msgctxt "@tooltip"
+msgid "Skirt"
+msgstr "Helma"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:84
+msgctxt "@tooltip"
+msgid "Prime Tower"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:85
+msgctxt "@tooltip"
+msgid "Travel"
+msgstr "Siirtoliike"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:86
+msgctxt "@tooltip"
+msgid "Retractions"
+msgstr "Takaisinvedot"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:87
+msgctxt "@tooltip"
+msgid "Other"
+msgstr "Muu"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:302
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "Esiviipaloitu tiedosto {0}"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+msgctxt "@action:button"
+msgid "Next"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:62
#, python-brace-format
msgctxt "@label"
msgid "Group #{group_nr}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:65
-msgctxt "@info:title"
-msgid "Network enabled printers"
+#: /home/ruben/Projects/Cura/cura/UI/WhatsNewPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:169
+msgctxt "@action:button"
+msgid "Close"
+msgstr "Sulje"
+
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Lisää"
+
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:18
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:352
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:58
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:149
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:406
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:294
+msgctxt "@action:button"
+msgid "Cancel"
+msgstr "Peruuta"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:36
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:320
+msgctxt "@label"
+msgid "Default"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:80
-msgctxt "@info:title"
-msgid "Local printers"
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:39
+msgctxt "@label"
+msgid "Visual"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:40
+msgctxt "@text"
+msgid "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:43
+msgctxt "@label"
+msgid "Engineering"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:44
+msgctxt "@text"
+msgid "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:47
+msgctxt "@label"
+msgid "Draft"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:48
+msgctxt "@text"
+msgid "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:357
+msgctxt "@label"
+msgid "Custom profiles"
+msgstr "Mukautetut profiilit"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:391
#, python-brace-format
msgctxt "@item:inlistbox"
msgid "All Supported Types ({0})"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:110
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:392
msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:665
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:213
msgctxt "@label"
msgid "Custom Material"
msgstr "Mukautettu materiaali"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:666
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:256
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:214
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:205
msgctxt "@label"
msgid "Custom"
msgstr "Mukautettu"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:116
+msgctxt "@label"
+msgid "The printer(s) below cannot be connected because they are part of a group"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:118
+msgctxt "@label"
+msgid "Available networked printers"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:90
msgctxt "@info:status"
msgid "The build volume height has been reduced due to the value of the \"Print Sequence\" setting to prevent the gantry from colliding with printed models."
msgstr "Tulostustilavuuden korkeutta on vähennetty tulostusjärjestysasetuksen vuoksi, jotta koroke ei osuisi tulostettuihin malleihin."
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:83
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:92
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Tulostustilavuus"
@@ -1195,52 +1075,67 @@ msgctxt "@info:backup_failed"
msgid "Tried to restore a Cura backup without having proper data or meta data."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:124
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:125
msgctxt "@info:backup_failed"
-msgid "Tried to restore a Cura backup that does not match your current version."
+msgid "Tried to restore a Cura backup that is higher than the current version."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
msgctxt "@info"
msgid "Unable to reach the Ultimaker account server."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:70
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:77
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:29
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Kappaleiden kertominen ja sijoittelu"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:30
msgctxt "@info:title"
msgid "Placing Objects"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:149
msgctxt "@info:status"
msgid "Unable to find a location within the build volume for all objects"
msgstr "Kaikille kappaleille ei löydy paikkaa tulostustilavuudessa."
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Sijoitetaan kappaletta"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:30
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:67
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:66
msgctxt "@info:status"
msgid "Finding new location for objects"
msgstr "Uusien paikkojen etsiminen kappaleille"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:34
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:71
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:70
msgctxt "@info:title"
msgid "Finding Location"
msgstr "Etsitään paikkaa"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Paikkaa ei löydy"
@@ -1363,242 +1258,205 @@ msgstr ""
#: /home/ruben/Projects/Cura/cura/CrashHandler.py:322
msgctxt "@title:groupbox"
-msgid "User description"
+msgid "User description (Note: Developers may not speak your language, please use English if possible)"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:341
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:480
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:513
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Ladataan laitteita..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:781
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:520
+msgctxt "@info:progress"
+msgid "Setting up preferences..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:824
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Asetetaan näkymää..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:817
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:859
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Ladataan käyttöliittymää..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1059
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1150
#, python-format
msgctxt "@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm."
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr "%(width).1f x %(depth).1f x %(height).1f mm"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1618
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1657
#, python-brace-format
msgctxt "@info:status"
msgid "Only one G-code file can be loaded at a time. Skipped importing {0}"
msgstr "Vain yksi G-code-tiedosto voidaan ladata kerralla. Tiedoston {0} tuonti ohitettiin."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1628
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1667
#, python-brace-format
msgctxt "@info:status"
msgid "Can't open any other file if G-code is loading. Skipped importing {0}"
msgstr "Muita tiedostoja ei voida ladata, kun G-code latautuu. Tiedoston {0} tuonti ohitettiin."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1718
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1757
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:62
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Laitteen asetukset"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:81
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Tulostin"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:100
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:56
+msgctxt "@title:label"
msgid "Printer Settings"
-msgstr "Tulostimen asetukset"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:70
msgctxt "@label"
msgid "X (Width)"
msgstr "X (leveys)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:112
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:122
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:132
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:387
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:429
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:441
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:897
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:74
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:88
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:102
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:243
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:265
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:285
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:79
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:93
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:109
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:124
msgctxt "@label"
msgid "mm"
msgstr "mm"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:84
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (syvyys)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:98
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (korkeus)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:143
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:112
msgctxt "@label"
msgid "Build plate shape"
msgstr "Alustan muoto"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:152
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:125
+msgctxt "@label"
msgid "Origin at center"
-msgstr "Alkukohta keskellä"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:160
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:137
+msgctxt "@label"
msgid "Heated bed"
-msgstr "Lämmitettävä pöytä"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:171
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:149
+msgctxt "@label"
+msgid "Heated build volume"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:161
msgctxt "@label"
msgid "G-code flavor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:184
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:185
+msgctxt "@title:label"
msgid "Printhead Settings"
-msgstr "Tulostuspään asetukset"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:199
msgctxt "@label"
msgid "X min"
msgstr "X väh."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:195
-msgctxt "@tooltip"
-msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Etäisyys tulostuspään vasemmalta puolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:219
msgctxt "@label"
msgid "Y min"
msgstr "Y väh."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:205
-msgctxt "@tooltip"
-msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Etäisyys tulostuspään etupuolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:239
msgctxt "@label"
msgid "X max"
msgstr "X enint."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:215
-msgctxt "@tooltip"
-msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Etäisyys tulostuspään oikealta puolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:261
msgctxt "@label"
msgid "Y max"
msgstr "Y enint."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:225
-msgctxt "@tooltip"
-msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Etäisyys tulostuspään takapuolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:281
msgctxt "@label"
-msgid "Gantry height"
-msgstr "Korokkeen korkeus"
+msgid "Gantry Height"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:239
-msgctxt "@tooltip"
-msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
-msgstr "Suuttimen kärjen ja korokejärjestelmän (X- ja Y-akselit) välinen korkeusero. Käytetään estämään aiempien tulosteiden ja korokkeen yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:258
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:295
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Suulakkeiden määrä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:314
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:324
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:333
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:366
+msgctxt "@title:label"
msgid "End G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:343
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very end."
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:42
+msgctxt "@title:tab"
+msgid "Printer"
+msgstr "Tulostin"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:63
+msgctxt "@title:label"
+msgid "Nozzle Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:374
-msgctxt "@label"
-msgid "Nozzle Settings"
-msgstr "Suutinasetukset"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr "Suuttimen koko"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:404
-msgctxt "@tooltip"
-msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
-msgstr "Tulostimen tukema tulostuslangan nimellinen halkaisija. Materiaali ja/tai profiili korvaa tarkan halkaisijan."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:428
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Suuttimen X-siirtymä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:440
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:120
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Suuttimen Y-siirtymä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:452
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:135
msgctxt "@label"
msgid "Cooling Fan Number"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:453
-msgctxt "@label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:473
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:491
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr ""
@@ -1608,7 +1466,7 @@ msgid "Install"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Asennettu"
@@ -1623,16 +1481,16 @@ msgctxt "@label"
msgid "ratings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:28
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:32
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:30
msgctxt "@title:tab"
msgid "Plugins"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:69
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:42
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:361
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:77
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiaalit"
@@ -1642,52 +1500,49 @@ msgctxt "@label"
msgid "Your rating"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:98
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:99
msgctxt "@label"
msgid "Version"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:105
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:106
msgctxt "@label"
msgid "Last updated"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:112
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:260
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:113
msgctxt "@label"
msgid "Author"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:119
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:120
msgctxt "@label"
msgid "Downloads"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:181
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:222
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:265
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Tuntematon"
-
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:56
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to install or update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:73
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:80
+msgctxt "@label:The string between and is the highlighted link"
+msgid "Buy material spools"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:96
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:34
msgctxt "@action:button"
msgid "Update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:74
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:97
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:35
msgctxt "@action:button"
msgid "Updating"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:75
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:98
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:36
msgctxt "@action:button"
msgid "Updated"
@@ -1748,22 +1603,22 @@ msgctxt "@info:button"
msgid "Quit Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Contributions"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Plugins"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:43
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:40
msgctxt "@label"
msgid "Generic Materials"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:56
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr ""
@@ -1816,27 +1671,47 @@ msgctxt "@label"
msgid "Featured"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:34
msgctxt "@label"
msgid "Compatibility"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:124
+msgctxt "@label:table_header"
+msgid "Machine"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:137
+msgctxt "@label:table_header"
+msgid "Build Plate"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:143
+msgctxt "@label:table_header"
+msgid "Support"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:149
+msgctxt "@label:table_header"
+msgid "Quality"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:170
msgctxt "@action:label"
msgid "Technical Data Sheet"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:179
msgctxt "@action:label"
msgid "Safety Data Sheet"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:188
msgctxt "@action:label"
msgid "Printing Guidelines"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:197
msgctxt "@action:label"
msgid "Website"
msgstr ""
@@ -1846,12 +1721,12 @@ msgctxt "@info"
msgid "Fetching packages..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:90
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:91
msgctxt "@label"
msgid "Website"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:97
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr ""
@@ -1861,22 +1736,6 @@ msgctxt "@info:tooltip"
msgid "Some things could be problematic in this print. Click to see tips for adjustment."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
-msgctxt "@label"
-msgid "Changelog"
-msgstr "Muutosloki"
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:85
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
-msgctxt "@action:button"
-msgid "Close"
-msgstr "Sulje"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
msgctxt "@title"
msgid "Update Firmware"
@@ -1952,58 +1811,66 @@ msgctxt "@label"
msgid "Firmware update failed due to missing firmware."
msgstr "Laiteohjelmiston päivitys epäonnistui puuttuvan laiteohjelmiston takia."
-#: /home/ruben/Projects/Cura/plugins/UserAgreement/UserAgreement.qml:16
-msgctxt "@title:window"
-msgid "User Agreement"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:155
+msgctxt "@label link to Connect and Cloud interfaces"
+msgid "Manage printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:254
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:192
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:183
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:256
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:514
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:248
msgctxt "@info"
-msgid "These options are not available because you are monitoring a cloud printer."
+msgid "Please update your printer's firmware to manage the queue remotely."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:289
msgctxt "@info"
msgid "The webcam is not available because you are monitoring a cloud printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:301
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:348
msgctxt "@label:status"
msgid "Loading..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:305
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:352
msgctxt "@label:status"
msgid "Unavailable"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:309
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:356
msgctxt "@label:status"
msgid "Unreachable"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:360
msgctxt "@label:status"
msgid "Idle"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
msgctxt "@label"
msgid "Untitled"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:373
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:422
msgctxt "@label"
msgid "Anonymous"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:399
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:449
msgctxt "@label:status"
msgid "Requires configuration changes"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:436
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:487
msgctxt "@action:button"
msgid "Details"
msgstr ""
@@ -2018,12 +1885,6 @@ msgctxt "@label"
msgid "First available"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:187
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:132
-msgctxt "@label"
-msgid "Glass"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
msgctxt "@label"
msgid "Queued"
@@ -2031,196 +1892,193 @@ msgstr "Jonossa"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
msgctxt "@label link to connect manager"
-msgid "Go to Cura Connect"
+msgid "Manage in browser"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:100
+msgctxt "@label"
+msgid "There are no print jobs in the queue. Slice and send a job to add one."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:115
msgctxt "@label"
msgid "Print jobs"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:131
msgctxt "@label"
msgid "Total print time"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:130
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:147
msgctxt "@label"
msgid "Waiting for"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:246
-msgctxt "@label link to connect manager"
-msgid "View print history"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:46
-msgctxt "@window:title"
-msgid "Existing Connection"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:48
-msgctxt "@message:text"
-msgid "This printer/group is already added to Cura. Please select another printer/group."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:65
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Yhdistä verkkotulostimeen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
msgctxt "@label"
-msgid ""
-"To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
-"\n"
-"Select your printer from the list below:"
+msgid "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer."
msgstr ""
-"Tulosta suoraan tulostimeen verkon kautta yhdistämällä tulostin verkkoon verkkokaapelilla tai yhdistämällä tulostin Wi-Fi-verkkoon. Jos Curaa ei yhdistetä tulostimeen, GCode-tiedostot voidaan silti siirtää tulostimeen USB-aseman avulla.\n"
-"\n"
-"Valitse tulostin alla olevasta luettelosta:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Lisää"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
+msgctxt "@label"
+msgid "Select your printer from the list below:"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:97
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
msgctxt "@action:button"
msgid "Edit"
msgstr "Muokkaa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:108
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:138
msgctxt "@action:button"
msgid "Remove"
msgstr "Poista"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:96
msgctxt "@action:button"
msgid "Refresh"
msgstr "Päivitä"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:211
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:176
msgctxt "@label"
msgid "If your printer is not listed, read the network printing troubleshooting guide"
msgstr "Jos tulostinta ei ole luettelossa, lue verkkotulostuksen vianetsintäopas"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:240
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:258
msgctxt "@label"
msgid "Type"
msgstr "Tyyppi"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:279
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:274
msgctxt "@label"
msgid "Firmware version"
msgstr "Laiteohjelmistoversio"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:290
msgctxt "@label"
msgid "Address"
msgstr "Osoite"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:317
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:263
msgctxt "@label"
msgid "This printer is not set up to host a group of printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:267
msgctxt "@label"
msgid "This printer is the host for a group of %1 printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:332
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:278
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr "Tämän osoitteen tulostin ei ole vielä vastannut."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:337
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
msgctxt "@action:button"
msgid "Connect"
msgstr "Yhdistä"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:351
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:296
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:146
+msgctxt "@text"
+msgid "Please enter a valid IP address."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:308
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Tulostimen osoite"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:374
-msgctxt "@alabel"
-msgid "Enter the IP address or hostname of your printer on the network."
-msgstr "Anna verkon tulostimen IP-osoite tai isäntänimi."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
+msgid "Enter the IP address of your printer on the network."
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:404
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:361
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:138
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
msgstr "OK"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
msgctxt "@label:status"
msgid "Aborted"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:80
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:82
msgctxt "@label:status"
msgid "Finished"
msgstr "Valmis"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:86
msgctxt "@label:status"
msgid "Preparing..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
msgctxt "@label:status"
msgid "Aborting..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
msgctxt "@label:status"
msgid "Pausing..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:104
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
msgctxt "@label:status"
msgid "Paused"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
msgctxt "@label:status"
msgid "Resuming..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:108
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
msgctxt "@label:status"
msgid "Action required"
msgstr "Vaatii toimenpiteitä"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:110
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
msgctxt "@label:status"
msgid "Finishes %1 at %2"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:44
-msgctxt "@action:button"
-msgid "Print"
-msgstr "Tulosta"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:11
msgctxt "@title:window"
msgid "Print over network"
msgstr "Tulosta verkon kautta"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:52
+msgctxt "@action:button"
+msgid "Print"
+msgstr "Tulosta"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:80
msgctxt "@label"
msgid "Printer selection"
msgstr ""
@@ -2309,154 +2167,145 @@ msgctxt "@action:button"
msgid "Override"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:64
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:85
msgctxt "@label"
msgid "The assigned printer, %1, requires the following configuration change:"
msgid_plural "The assigned printer, %1, requires the following configuration changes:"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:68
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:89
msgctxt "@label"
msgid "The printer %1 is assigned, but the job contains an unknown material configuration."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:99
msgctxt "@label"
msgid "Change material %1 from %2 to %3."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:102
msgctxt "@label"
msgid "Load %3 as material %1 (This cannot be overridden)."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:105
msgctxt "@label"
msgid "Change print core %1 from %2 to %3."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:108
msgctxt "@label"
msgid "Change build plate to %1 (This cannot be overridden)."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:94
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:115
msgctxt "@label"
msgid "Override will use the specified settings with the existing printer configuration. This may result in a failed print."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:135
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:156
msgctxt "@label"
msgid "Aluminum"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:75
-msgctxt "@info:tooltip"
-msgid "Connect to a printer"
-msgstr "Yhdistä tulostimeen"
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:92
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:100
msgctxt "@info"
msgid ""
"Please make sure your printer has a connection:\n"
"- Check if the printer is turned on.\n"
-"- Check if the printer is connected to the network."
+"- Check if the printer is connected to the network.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:110
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
msgctxt "@info"
-msgid "Please select a network connected printer to monitor."
+msgid "Please connect your printer to the network."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:126
-msgctxt "@info"
-msgid "Please connect your Ultimaker printer to your local network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:165
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
msgctxt "@label link to technical assistance"
msgid "View user manuals online"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:18
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:47
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr "Värimalli"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:105
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Materiaalin väri"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:109
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Linjojen tyyppi"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:113
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:117
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:154
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Yhteensopivuustila"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:229
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
msgid "Travels"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:235
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
msgid "Helpers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:241
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
msgid "Shell"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:247
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
msgid "Infill"
msgstr "Täyttö"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Näytä vain yläkerrokset"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:307
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:308
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr "Näytä 5 yksityiskohtaista kerrosta ylhäällä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Yläosa/alaosa"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:325
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Sisäseinämä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:432
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr ""
@@ -2486,29 +2335,24 @@ msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Muuta aktiivisia jälkikäsittelykomentosarjoja"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:16
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:17
msgctxt "@title:window"
msgid "More information on anonymous data collection"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:66
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:74
msgctxt "@text:window"
-msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
+msgid "Ultimaker Cura collects anonymous data in order to improve the print quality and user experience. Below is an example of all the data that is shared:"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:101
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:109
msgctxt "@text:window"
-msgid "I don't want to send this data"
+msgid "I don't want to send anonymous data"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:111
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:118
msgctxt "@text:window"
-msgid "Allow sending this data to Ultimaker and help us improve Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/R2D2/EvaluationSidebar.qml:49
-msgctxt "@label"
-msgid "No print selected"
+msgid "Allow sending anonymous data"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
@@ -2558,19 +2402,19 @@ msgstr "Syvyys (mm)"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:126
msgctxt "@info:tooltip"
-msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
-msgstr "Oletuksena valkoiset pikselit edustavat verkossa korkeita pisteitä ja mustat pikselit edustavat verkossa matalia pisteitä. Muuta asetus, jos haluat, että mustat pikselit edustavat verkossa korkeita pisteitä ja valkoiset pikselit edustavat verkossa matalia pisteitä."
-
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
-msgctxt "@item:inlistbox"
-msgid "Lighter is higher"
-msgstr "Vaaleampi on korkeampi"
+msgid "For lithophanes dark pixels should correspond to thicker locations in order to block more light coming through. For height maps lighter pixels signify higher terrain, so lighter pixels should correspond to thicker locations in the generated 3D model."
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
msgctxt "@item:inlistbox"
msgid "Darker is higher"
msgstr "Tummempi on korkeampi"
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
+msgctxt "@item:inlistbox"
+msgid "Lighter is higher"
+msgstr "Vaaleampi on korkeampi"
+
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:149
msgctxt "@info:tooltip"
msgid "The amount of smoothing to apply to the image."
@@ -2581,72 +2425,71 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Tasoitus"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:37
-msgctxt "@label"
-msgid "Mesh Type"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:68
-msgctxt "@label"
-msgid "Normal model"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:75
-msgctxt "@label"
-msgid "Print as support"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:83
-msgctxt "@label"
-msgid "Don't support overlap with other models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:91
-msgctxt "@label"
-msgid "Modify settings for overlap with other models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:99
-msgctxt "@label"
-msgid "Modify settings for infill of other models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
-msgctxt "@action:button"
-msgid "Select settings"
-msgstr "Valitse asetukset"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:13
msgctxt "@title:window"
msgid "Select Settings to Customize for this model"
msgstr "Valitse tätä mallia varten mukautettavat asetukset"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:431
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:56
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Suodatin..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:445
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:70
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Näytä kaikki"
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:44
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:85
+msgctxt "@label"
+msgid "Normal model"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:97
+msgctxt "@label"
+msgid "Print as support"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:109
+msgctxt "@label"
+msgid "Modify settings for overlaps"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:121
+msgctxt "@label"
+msgid "Don't support overlaps"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:145
+msgctxt "@action:checkbox"
+msgid "Infill only"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:368
+msgctxt "@action:button"
+msgid "Select settings"
+msgstr "Valitse asetukset"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:14
msgctxt "@title:window"
msgid "Open Project"
msgstr "Avaa projekti"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:58
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Update/override existing profile"
msgid "Update existing"
-msgstr "Päivitä nykyinen"
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:59
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Save settings in a new profile"
msgid "Create new"
-msgstr "Luo uusi"
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
@@ -2671,6 +2514,11 @@ msgctxt "@action:ComboBox option"
msgid "Update"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
+msgctxt "@action:ComboBox option"
+msgid "Create new"
+msgstr "Luo uusi"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
@@ -2684,7 +2532,7 @@ msgid "Printer Group"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:220
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Profiilin asetukset"
@@ -2695,75 +2543,81 @@ msgid "How should the conflict in the profile be resolved?"
msgstr "Miten profiilin ristiriita pitäisi ratkaista?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:323
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:221
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:244
msgctxt "@action:label"
msgid "Name"
msgstr "Nimi"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:261
+msgctxt "@action:label"
+msgid "Intent"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:228
msgctxt "@action:label"
msgid "Not in profile"
msgstr "Ei profiilissa"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:210
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:233
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
msgstr[0] "%1 ohitus"
msgstr[1] "%1 ohitusta"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:247
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:262
msgctxt "@action:label"
msgid "Derivative from"
msgstr "Johdettu seuraavista"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:252
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:267
msgctxt "@action:label"
msgid "%1, %2 override"
msgid_plural "%1, %2 overrides"
msgstr[0] "%1, %2 ohitus"
msgstr[1] "%1, %2 ohitusta"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:268
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:283
msgctxt "@action:label"
msgid "Material settings"
msgstr "Materiaaliasetukset"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:284
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:299
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
msgstr "Miten materiaalin ristiriita pitäisi ratkaista?"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:342
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Asetusten näkyvyys"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:336
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:351
msgctxt "@action:label"
msgid "Mode"
msgstr "Tila"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:367
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Näkyvät asetukset:"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:372
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1/%2"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:383
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:398
msgctxt "@action:warning"
msgid "Loading a project will clear all models on the build plate."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:401
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:416
msgctxt "@action:button"
msgid "Open"
msgstr "Avaa"
@@ -2790,6 +2644,7 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:51
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:138
msgctxt "@button"
msgid "Sign in"
msgstr ""
@@ -2869,187 +2724,41 @@ msgctxt "@checkbox:description"
msgid "Automatically create a backup each day that Cura is started."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMainSettingsSelector.qml:75
-msgctxt "@label"
-msgid "Not supported"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:35
-msgctxt "@action:button"
-msgid "Previous"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
-msgctxt "@action:button"
-msgid "Export"
-msgstr "Vie"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
-msgctxt "@action:button"
-msgid "Next"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:169
-msgctxt "@label"
-msgid "Tip"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:160
-msgctxt "@label"
-msgid "Print experiment"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageValidation.qml:25
-msgctxt "@label"
-msgid "Checklist"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:26
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:25
-msgctxt "@title"
-msgid "Select Printer Upgrades"
-msgstr "Valitse tulostimen päivitykset"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:38
-msgctxt "@label"
-msgid "Please select any upgrades made to this Ultimaker 2."
-msgstr "Valitse tähän Ultimaker 2 -laitteeseen tehdyt päivitykset."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
-msgctxt "@label"
-msgid "Olsson Block"
-msgstr "Olsson Block -lämmitysosa"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:30
msgctxt "@title"
msgid "Build Plate Leveling"
msgstr "Alustan tasaaminen"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:38
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:44
msgctxt "@label"
msgid "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted."
msgstr "Voit säätää alustaa, jotta tulosteista tulisi hyviä. Kun napsautat \"Siirry seuraavaan positioon\", suutin siirtyy eri positioihin, joita voidaan säätää."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:57
msgctxt "@label"
msgid "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle."
msgstr "Laita paperinpala kussakin positiossa suuttimen alle ja säädä tulostusalustan korkeus. Tulostusalustan korkeus on oikea, kun suuttimen kärki juuri ja juuri osuu paperiin."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:62
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:75
msgctxt "@action:button"
msgid "Start Build Plate Leveling"
msgstr "Aloita alustan tasaaminen"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:74
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:87
msgctxt "@action:button"
msgid "Move to Next Position"
msgstr "Siirry seuraavaan positioon"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:37
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker Original"
msgstr "Valitse tähän Ultimaker Original -laitteeseen tehdyt päivitykset"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:45
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:41
msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Lämmitettävä alusta (virallinen sarja tai itse rakennettu)"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
-msgctxt "@title"
-msgid "Check Printer"
-msgstr "Tarkista tulostin"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
-msgctxt "@label"
-msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
-msgstr "Ultimakerille on hyvä tehdä muutamia toimintatarkastuksia. Voit jättää tämän vaiheen väliin, jos tiedät laitteesi olevan toimintakunnossa"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
-msgctxt "@action:button"
-msgid "Start Printer Check"
-msgstr "Aloita tulostintarkistus"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
-msgctxt "@label"
-msgid "Connection: "
-msgstr "Yhteys: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Connected"
-msgstr "Yhdistetty"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Not connected"
-msgstr "Ei yhteyttä"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
-msgctxt "@label"
-msgid "Min endstop X: "
-msgstr "Min. päätyraja X: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-msgctxt "@info:status"
-msgid "Works"
-msgstr "Toimii"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Not checked"
-msgstr "Ei tarkistettu"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
-msgctxt "@label"
-msgid "Min endstop Y: "
-msgstr "Min. päätyraja Y: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
-msgctxt "@label"
-msgid "Min endstop Z: "
-msgstr "Min. päätyraja Z: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
-msgctxt "@label"
-msgid "Nozzle temperature check: "
-msgstr "Suuttimen lämpötilatarkistus: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Stop Heating"
-msgstr "Lopeta lämmitys"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Start Heating"
-msgstr "Aloita lämmitys"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
-msgctxt "@label"
-msgid "Build plate temperature check:"
-msgstr "Alustan lämpötilan tarkistus:"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Checked"
-msgstr "Tarkistettu"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
-msgctxt "@label"
-msgid "Everything is in order! You're done with your CheckUp."
-msgstr "Kaikki on kunnossa! CheckUp on valmis."
-
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
@@ -3100,170 +2809,176 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Haluatko varmasti keskeyttää tulostuksen?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
msgctxt "@title"
msgid "Information"
msgstr "Tiedot"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
msgctxt "@title:window"
msgid "Confirm Diameter Change"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:102
msgctxt "@label (%1 is a number)"
msgid "The new filament diameter is set to %1 mm, which is not compatible with the current extruder. Do you wish to continue?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:128
msgctxt "@label"
msgid "Display Name"
msgstr "Näytä nimi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:138
msgctxt "@label"
msgid "Brand"
msgstr "Merkki"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:148
msgctxt "@label"
msgid "Material Type"
msgstr "Materiaalin tyyppi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:158
msgctxt "@label"
msgid "Color"
msgstr "Väri"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:208
msgctxt "@label"
msgid "Properties"
msgstr "Ominaisuudet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:214
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:210
msgctxt "@label"
msgid "Density"
msgstr "Tiheys"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:229
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:225
msgctxt "@label"
msgid "Diameter"
msgstr "Läpimitta"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:259
msgctxt "@label"
msgid "Filament Cost"
msgstr "Tulostuslangan hinta"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:276
msgctxt "@label"
msgid "Filament weight"
msgstr "Tulostuslangan paino"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:294
msgctxt "@label"
msgid "Filament length"
msgstr "Tulostuslangan pituus"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:307
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:303
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Hinta metriä kohden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:317
msgctxt "@label"
msgid "This material is linked to %1 and shares some of its properties."
msgstr "Materiaali on linkitetty kohteeseen %1 ja niillä on joitain samoja ominaisuuksia."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:324
msgctxt "@label"
msgid "Unlink Material"
msgstr "Poista materiaalin linkitys"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:339
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:335
msgctxt "@label"
msgid "Description"
msgstr "Kuvaus"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:352
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:348
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Tarttuvuustiedot"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:17
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
msgctxt "@label"
msgid "Print settings"
msgstr "Tulostusasetukset"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:84
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:84
msgctxt "@action:button"
msgid "Activate"
msgstr "Aktivoi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:126
msgctxt "@action:button"
msgid "Create"
msgstr "Luo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:140
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Jäljennös"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:141
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:167
msgctxt "@action:button"
msgid "Import"
msgstr "Tuo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:203
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:179
+msgctxt "@action:button"
+msgid "Export"
+msgstr "Vie"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:233
msgctxt "@action:label"
msgid "Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:262
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:274
msgctxt "@title:window"
msgid "Confirm Remove"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:263
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:247
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:300
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:275
msgctxt "@label (%1 is object name)"
msgid "Are you sure you wish to remove %1? This cannot be undone!"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:277
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:285
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:322
msgctxt "@title:window"
msgid "Import Material"
msgstr "Tuo materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:323
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Could not import material %1: %2"
msgstr "Materiaalin tuominen epäonnistui: %1: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:327
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully imported material %1"
msgstr "Materiaalin tuominen onnistui: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:316
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:345
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:353
msgctxt "@title:window"
msgid "Export Material"
msgstr "Vie materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:357
msgctxt "@info:status Don't translate the XML tags and !"
msgid "Failed to export material to %1: %2"
msgstr "Materiaalin vieminen epäonnistui kohteeseen %1: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:363
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Materiaalin vieminen onnistui kohteeseen %1"
@@ -3278,412 +2993,422 @@ msgctxt "@label:textbox"
msgid "Check all"
msgstr "Tarkista kaikki"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:47
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:61
msgctxt "@info:status"
msgid "Calculated"
msgstr "Laskettu"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:75
msgctxt "@title:column"
msgid "Setting"
msgstr "Asetus"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
msgctxt "@title:column"
msgid "Profile"
msgstr "Profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:74
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:89
msgctxt "@title:column"
msgid "Current"
msgstr "Nykyinen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:97
msgctxt "@title:column"
msgid "Unit"
msgstr "Yksikkö"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr "Yleiset"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:126
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:132
msgctxt "@label"
msgid "Interface"
msgstr "Käyttöliittymä"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:143
msgctxt "@label"
msgid "Language:"
msgstr "Kieli:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:210
msgctxt "@label"
msgid "Currency:"
msgstr "Valuutta:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:223
msgctxt "@label"
msgid "Theme:"
msgstr "Teema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:273
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:279
msgctxt "@label"
msgid "You will need to restart the application for these changes to have effect."
msgstr "Sovellus on käynnistettävä uudelleen, jotta nämä muutokset tulevat voimaan."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:296
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Viipaloi automaattisesti, kun asetuksia muutetaan."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Viipaloi automaattisesti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:312
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Näyttöikkunan käyttäytyminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
msgctxt "@info:tooltip"
msgid "Highlight unsupported areas of the model in red. Without support these areas will not print properly."
msgstr "Korosta mallin vailla tukea olevat alueet punaisella. Ilman tukea nämä alueet eivät tulostu kunnolla."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:335
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Näytä uloke"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:343
msgctxt "@info:tooltip"
msgid "Moves the camera so the model is in the center of the view when a model is selected"
msgstr "Siirtää kameraa siten, että valittuna oleva malli on näkymän keskellä."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:348
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr "Keskitä kamera kun kohde on valittu"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Pitääkö Curan oletusarvoinen zoom-toimintatapa muuttaa päinvastaiseksi?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:355
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Käännä kameran zoomin suunta päinvastaiseksi."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr "Tuleeko zoomauksen siirtyä hiiren suuntaan?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
+msgctxt "@info:tooltip"
+msgid "Zooming towards the mouse is not supported in the orthographic perspective."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoomaa hiiren suuntaan"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:380
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:410
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved so that they no longer intersect?"
msgstr "Pitäisikö alustalla olevia malleja siirtää niin, etteivät ne enää leikkaa toisiaan?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:385
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr "Varmista, että mallit ovat erillään"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:394
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:424
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved down to touch the build plate?"
msgstr "Pitäisikö tulostusalueella olevia malleja siirtää alas niin, että ne koskettavat tulostusalustaa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:429
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr "Pudota mallit automaattisesti alustalle"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:411
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:428
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:458
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "Pakotetaanko kerros yhteensopivuustilaan?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:463
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr "Pakota kerrosnäkymän yhteensopivuustila (vaatii uudelleenkäynnistyksen)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
+msgctxt "@info:tooltip"
+msgid "Should Cura open at the location it was closed?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
+msgctxt "@option:check"
+msgid "Restore window position on start"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:488
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:495
+msgctxt "@window:text"
+msgid "Camera rendering:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+msgid "Perspective"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+msgid "Orthographic"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Tiedostojen avaaminen ja tallentaminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:456
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:545
msgctxt "@info:tooltip"
msgid "Should models be scaled to the build volume if they are too large?"
msgstr "Pitäisikö mallit skaalata tulostustilavuuteen, jos ne ovat liian isoja?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:461
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:550
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Skaalaa suuret mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:560
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Malli voi vaikuttaa erittäin pieneltä, jos sen koko on ilmoitettu esimerkiksi metreissä eikä millimetreissä. Pitäisikö nämä mallit suurentaa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:565
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Skaalaa erittäin pienet mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:491
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:580
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
msgctxt "@info:tooltip"
msgid "Should a prefix based on the printer name be added to the print job name automatically?"
msgstr "Pitäisikö tulostustyön nimeen lisätä automaattisesti tulostimen nimeen perustuva etuliite?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr "Lisää laitteen etuliite työn nimeen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:516
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:605
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr "Näytetäänkö yhteenveto, kun projektitiedosto tallennetaan?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:609
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr "Näytä yhteenvetoikkuna, kun projekti tallennetaan"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Projektitiedoston avaamisen oletustoimintatapa"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:627
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Projektitiedoston avaamisen oletustoimintatapa: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:642
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Avaa aina projektina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:554
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Tuo mallit aina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:679
msgctxt "@info:tooltip"
msgid "When you have made changes to a profile and switched to a different one, a dialog will be shown asking whether you want to keep your modifications or not, or you can choose a default behaviour and never show that dialog again."
msgstr "Kun olet tehnyt muutokset profiiliin ja vaihtanut toiseen, näytetään valintaikkuna, jossa kysytään, haluatko säilyttää vai hylätä muutokset. Tässä voit myös valita oletuskäytöksen, jolloin valintaikkunaa ei näytetä uudelleen."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:599
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:52
msgctxt "@label"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:693
msgctxt "@window:text"
msgid "Default behavior for changed setting values when switching to a different profile: "
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:707
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:157
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Kysy aina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:709
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:654
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
msgctxt "@label"
msgid "Privacy"
msgstr "Tietosuoja"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:661
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:750
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr "Pitäisikö Curan tarkistaa saatavilla olevat päivitykset, kun ohjelma käynnistetään?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:666
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:755
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Tarkista päivitykset käynnistettäessä"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:676
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:765
msgctxt "@info:tooltip"
msgid "Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored."
msgstr "Pitäisikö anonyymejä tietoja tulosteesta lähettää Ultimakerille? Huomaa, että malleja, IP-osoitteita tai muita henkilökohtaisia tietoja ei lähetetä eikä tallenneta."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:681
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:770
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Lähetä (anonyymit) tulostustiedot"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:690
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:779
msgctxt "@action:button"
msgid "More information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
-msgctxt "@label"
-msgid "Experimental"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:715
-msgctxt "@info:tooltip"
-msgid "Use multi build plate functionality"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
-msgctxt "@option:check"
-msgid "Use multi build plate functionality (restart required)"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:16
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr "Tulostimet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:57
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:63
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
msgctxt "@action:button"
msgid "Rename"
msgstr "Nimeä uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:363
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:419
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profiilit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:104
msgctxt "@label"
msgid "Create"
msgstr "Luo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@label"
msgid "Duplicate"
msgstr "Jäljennös"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:202
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Luo profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:176
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:204
msgctxt "@info"
msgid "Please provide a name for this profile."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:260
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Monista profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:291
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Nimeä profiili uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:276
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:304
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Profiilin tuonti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:333
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Profiilin vienti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:396
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Tulostin: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Default profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Custom profiles"
-msgstr "Mukautetut profiilit"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:554
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr "Päivitä nykyiset asetukset tai ohitukset profiiliin"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:561
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:257
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Hylkää tehdyt muutokset"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:514
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:580
msgctxt "@action:label"
msgid "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below."
msgstr "Tässä profiilissa käytetään tulostimen oletusarvoja, joten siinä ei ole alla olevan listan asetuksia tai ohituksia."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:521
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:588
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr "Nykyiset asetukset vastaavat valittua profiilia."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:606
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Yleiset asetukset"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:90
msgctxt "@action:button"
msgid "Marketplace"
msgstr ""
@@ -3726,12 +3451,12 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Ohje"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
msgctxt "@title:window"
msgid "New project"
msgstr "Uusi projekti"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:125
msgctxt "@info:question"
msgid "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings."
msgstr "Haluatko varmasti aloittaa uuden projektin? Se tyhjentää alustan ja kaikki tallentamattomat asetukset."
@@ -3743,36 +3468,36 @@ msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "search settings"
+msgid "Search settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:462
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Kopioi arvo kaikkiin suulakepuristimiin"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:474
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:471
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Piilota tämä asetus"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:521
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Älä näytä tätä asetusta"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Pidä tämä asetus näkyvissä"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:557
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Määritä asetusten näkyvyys..."
@@ -3788,27 +3513,32 @@ msgstr ""
"\n"
"Tee asetuksista näkyviä napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:81
+msgctxt "@label"
+msgid "This setting is not used because all the settings that it influences are overridden."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:86
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Koskee seuraavia:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:91
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Riippuu seuraavista:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:166
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:187
msgctxt "@label"
msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:191
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr "Arvo perustuu suulakepuristimien arvoihin "
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:230
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3819,7 +3549,7 @@ msgstr ""
"\n"
"Palauta profiilin arvo napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:329
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3830,12 +3560,19 @@ msgstr ""
"\n"
"Palauta laskettu arvo napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/NoIntentIcon.qml:31
+msgctxt "@label %1 is filled in with the type of a profile. %2 is filled with a list of numbers (eg '1' or '1, 2')"
+msgid "There is no %1 profile for the configuration in extruder %2. The default intent will be used instead"
+msgid_plural "There is no %1 profile for the configurations in extruders %2. The default intent will be used instead"
+msgstr[0] ""
+msgstr[1] ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
msgctxt "@button"
msgid "Recommended"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
msgctxt "@button"
msgid "Custom"
msgstr ""
@@ -3850,51 +3587,31 @@ msgctxt "@label"
msgid "Gradual infill will gradually increase the amount of infill towards the top."
msgstr "Asteittainen täyttö lisää täytön tiheyttä vähitellen yläosaa kohti."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:29
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:30
msgctxt "@label"
msgid "Support"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:71
msgctxt "@label"
msgid "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."
msgstr "Muodosta rakenteita, jotka tukevat mallin ulokkeita sisältäviä osia. Ilman tukirakenteita kyseiset osat luhistuvat tulostuksen aikana."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:136
-msgctxt "@label"
-msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
-msgstr "Valitse tukena käytettävä suulakepuristin. Näin mallin alle rakennetaan tukirakenteita estämään mallin painuminen tai tulostuminen ilmaan."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:29
msgctxt "@label"
msgid "Adhesion"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:74
msgctxt "@label"
msgid "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."
msgstr "Ota reunuksen tai pohjaristikon tulostus käyttöön. Tämä lisää kappaleen ympärille tai alle tasaisen alueen, joka on helppo leikata pois myöhemmin."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:175
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Kerroksen korkeus"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:206
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:81
msgctxt "@tooltip"
msgid "You have modified some profile settings. If you want to change these go to custom mode."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:355
-msgctxt "@tooltip"
-msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:449
-msgctxt "@tooltip"
-msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:13
msgctxt "@label:Should be short"
msgid "On"
@@ -3905,12 +3622,17 @@ msgctxt "@label:Should be short"
msgid "Off"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:33
+msgctxt "@label"
+msgid "Experimental"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:47
msgctxt "@label"
msgid "Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:172
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3921,9 +3643,14 @@ msgstr ""
"\n"
"Avaa profiilin hallinta napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:160
+msgctxt "@label:header"
+msgid "Custom profiles"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:21
msgctxt "@label shown when we load a Gcode file"
-msgid "Print setup disabled. G code file can not be modified."
+msgid "Print setup disabled. G-code file can not be modified."
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
@@ -3956,59 +3683,59 @@ msgctxt "@label"
msgid "Send G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:364
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:365
msgctxt "@tooltip of G-code command input"
msgid "Send a custom G-code command to the connected printer. Press 'enter' to send the command."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:41
msgctxt "@label"
msgid "Extruder"
msgstr "Suulake"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:71
msgctxt "@tooltip"
msgid "The target temperature of the hotend. The hotend will heat up or cool down towards this temperature. If this is 0, the hotend heating is turned off."
msgstr "Kuuman pään kohdelämpötila. Kuuma pää lämpenee tai viilenee kohti tätä lämpötilaa. Jos asetus on 0, kuuman pään lämmitys sammutetaan."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:103
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:177
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:332
msgctxt "@button Cancel pre-heating"
msgid "Cancel"
msgstr "Peruuta"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:344
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:335
msgctxt "@button"
msgid "Pre-heat"
msgstr "Esilämmitä"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:370
msgctxt "@tooltip of pre-heat"
msgid "Heat the hotend in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the hotend to heat up when you're ready to print."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:406
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr "Tämän suulakkeen materiaalin väri."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:438
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Tämän suulakkeen materiaali."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:470
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Tähän suulakkeeseen liitetty suutin."
@@ -4048,12 +3775,12 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:46
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:71
msgctxt "@label:category menu label"
msgid "Generic"
msgstr ""
@@ -4073,42 +3800,47 @@ msgctxt "@title:menu menubar:settings"
msgid "&Printer"
msgstr "&Tulostin"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:26
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:27
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:36
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Aseta aktiiviseksi suulakepuristimeksi"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Enable Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:49
msgctxt "@action:inmenu"
msgid "Disable Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:62
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:65
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profiili"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:19
msgctxt "@action:inmenu menubar:view"
msgid "&Camera position"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:44
+msgctxt "@action:inmenu menubar:view"
+msgid "Camera view"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:47
+msgctxt "@action:inmenu menubar:view"
+msgid "Perspective"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:59
+msgctxt "@action:inmenu menubar:view"
+msgid "Orthographic"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:80
msgctxt "@action:inmenu menubar:view"
msgid "&Build plate"
msgstr ""
@@ -4128,17 +3860,17 @@ msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:33
msgctxt "@title:menu menubar:file"
msgid "&Save..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:54
msgctxt "@title:menu menubar:file"
msgid "&Export..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:65
msgctxt "@action:inmenu menubar:file"
msgid "Export Selection..."
msgstr ""
@@ -4167,17 +3899,12 @@ msgctxt "@header"
msgid "Configurations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:112
msgctxt "@label"
msgid "Select configuration"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:201
-msgctxt "@label"
-msgid "See the material compatibility chart"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:274
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:223
msgctxt "@label"
msgid "Configurations"
msgstr ""
@@ -4202,17 +3929,17 @@ msgctxt "@label"
msgid "Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:202
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
msgctxt "@label"
msgid "Enabled"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:251
msgctxt "@label"
msgid "Material"
msgstr "Materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:344
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:378
msgctxt "@label"
msgid "Use glue for better adhesion with this material combination."
msgstr ""
@@ -4232,42 +3959,47 @@ msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr "Avaa &viimeisin"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr "Aktiivinen tulostustyö"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr "Työn nimi"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Tulostusaika"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:169
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr "Aikaa jäljellä arviolta"
#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
msgctxt "@label"
-msgid "View types"
+msgid "View type"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
msgctxt "@label"
-msgid "Hi "
+msgid "Object list"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:22
+msgctxt "@label The argument is a username."
+msgid "Hi %1"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:33
msgctxt "@button"
msgid "Ultimaker account"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
msgctxt "@button"
msgid "Sign out"
msgstr ""
@@ -4277,11 +4009,6 @@ msgctxt "@action:button"
msgid "Sign in"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:29
-msgctxt "@label"
-msgid "Ultimaker Cloud"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
msgctxt "@label"
msgid "The next generation 3D printing workflow"
@@ -4292,7 +4019,7 @@ msgctxt "@text"
msgid ""
"- Send print jobs to Ultimaker printers outside your local network\n"
"- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
-"- Get exclusive access to material profiles from leading brands"
+"- Get exclusive access to print profiles from leading brands"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
@@ -4305,49 +4032,54 @@ msgctxt "@label"
msgid "No time estimation available"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:76
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
msgctxt "@label"
msgid "No cost estimation available"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
msgctxt "@button"
msgid "Preview"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:55
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Viipaloidaan..."
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:61
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:67
msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "Viipalointi ei onnistu"
+msgid "Unable to slice"
+msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:116
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
+msgctxt "@button"
+msgid "Processing"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
msgctxt "@button"
msgid "Slice"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
msgctxt "@label"
msgid "Start the slicing process"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
msgctxt "@button"
msgid "Cancel"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
msgctxt "@label"
-msgid "Time specification"
+msgid "Time estimation"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
msgctxt "@label"
-msgid "Material specification"
+msgid "Material estimation"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
@@ -4370,285 +4102,299 @@ msgctxt "@label"
msgid "Preset printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
msgctxt "@button"
msgid "Add printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:173
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
msgctxt "@button"
msgid "Manage printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
msgctxt "@action:inmenu"
msgid "Show Online Troubleshooting Guide"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr "Vaihda koko näyttöön"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
+msgctxt "@action:inmenu"
+msgid "Exit Full Screen"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:103
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Kumoa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:113
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "Tee &uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:123
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Lopeta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:131
msgctxt "@action:inmenu menubar:view"
msgid "3D View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:138
msgctxt "@action:inmenu menubar:view"
msgid "Front View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:145
msgctxt "@action:inmenu menubar:view"
msgid "Top View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:152
msgctxt "@action:inmenu menubar:view"
msgid "Left Side View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:159
msgctxt "@action:inmenu menubar:view"
msgid "Right Side View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Määritä Curan asetukset..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:173
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "L&isää tulostin..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:179
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Tulostinten &hallinta..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Hallitse materiaaleja..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195
msgctxt "@action:inmenu menubar:profile"
msgid "&Update profile with current settings/overrides"
msgstr "&Päivitä nykyiset asetukset tai ohitukset profiiliin"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:192
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Hylkää tehdyt muutokset"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr "&Luo profiili nykyisten asetusten tai ohitusten perusteella..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Profiilien hallinta..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:229
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Näytä sähköinen &dokumentaatio"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:237
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Ilmoita &virheestä"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:245
+msgctxt "@action:inmenu menubar:help"
+msgid "What's New"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
msgctxt "@action:inmenu menubar:help"
msgid "About..."
msgstr "Tietoja..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:258
msgctxt "@action:inmenu menubar:edit"
msgid "Delete Selected Model"
msgid_plural "Delete Selected Models"
msgstr[0] "Poista valittu malli"
msgstr[1] "Poista valitut mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
msgctxt "@action:inmenu menubar:edit"
msgid "Center Selected Model"
msgid_plural "Center Selected Models"
msgstr[0] "Keskitä valittu malli"
msgstr[1] "Keskitä valitut mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
msgctxt "@action:inmenu menubar:edit"
msgid "Multiply Selected Model"
msgid_plural "Multiply Selected Models"
msgstr[0] "Kerro valittu malli"
msgstr[1] "Kerro valitut mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Poista malli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:294
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Ke&skitä malli alustalle"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:283
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:300
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "&Ryhmittele mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:303
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:320
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Poista mallien ryhmitys"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:313
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "&Yhdistä mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "&Kerro malli..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:347
msgctxt "@action:inmenu menubar:edit"
msgid "Select All Models"
msgstr "Valitse kaikki mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:357
msgctxt "@action:inmenu menubar:edit"
msgid "Clear Build Plate"
msgstr "Tyhjennä tulostusalusta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:367
msgctxt "@action:inmenu menubar:file"
msgid "Reload All Models"
msgstr "Lataa kaikki mallit uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:376
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models To All Build Plates"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:383
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Järjestä kaikki mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:391
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Järjestä valinta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:381
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:398
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr "Määritä kaikkien mallien positiot uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:405
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Transformations"
msgstr "Määritä kaikkien mallien muutokset uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:412
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Avaa tiedosto(t)..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:420
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Uusi projekti..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:427
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Näytä määrityskansio"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
msgid "&Marketplace"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:181
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
msgctxt "@label"
msgid "This package will be installed after restarting."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Asetukset"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:538
msgctxt "@title:window"
msgid "Closing Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:487
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:499
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:551
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:589
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:19
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Avaa tiedosto(t)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:632
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:695
msgctxt "@window:title"
msgid "Install Package"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:640
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:703
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Avaa tiedosto(t)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:643
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:706
msgctxt "@text:window"
msgid "We have found one or more G-Code files within the files you have selected. You can only open one G-Code file at a time. If you want to open a G-Code file, please just select only one."
msgstr "Löysimme vähintään yhden Gcode-tiedoston valitsemiesi tiedostojen joukosta. Voit avata vain yhden Gcode-tiedoston kerrallaan. Jos haluat avata Gcode-tiedoston, valitse vain yksi."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:713
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:18
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:809
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Lisää tulostin"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:817
+msgctxt "@title:window"
+msgid "What's New"
+msgstr ""
+
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
msgctxt "@label %1 is filled in with the name of an extruder"
msgid "Print Selected Model with %1"
@@ -4710,50 +4456,22 @@ msgctxt "@action:button"
msgid "Create New Profile"
msgstr "Luo uusi profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:78
-msgctxt "@title:tab"
-msgid "Add a printer to Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:92
-msgctxt "@title:tab"
-msgid ""
-"Select the printer you want to use from the list below.\n"
-"\n"
-"If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:249
-msgctxt "@label"
-msgid "Manufacturer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:271
-msgctxt "@label"
-msgid "Printer Name"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:294
-msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Lisää tulostin"
-
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:15
msgctxt "@title:window"
msgid "About Cura"
msgstr "Tietoja Curasta"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:56
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:57
msgctxt "@label"
msgid "version: %1"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:72
msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing."
msgstr "Kokonaisvaltainen sulatettavan tulostuslangan 3D-tulostusratkaisu."
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:85
msgctxt "@info:credit"
msgid ""
"Cura is developed by Ultimaker B.V. in cooperation with the community.\n"
@@ -4762,122 +4480,122 @@ msgstr ""
"Cura-ohjelman on kehittänyt Ultimaker B.V. yhteistyössä käyttäjäyhteisön kanssa.\n"
"Cura hyödyntää seuraavia avoimeen lähdekoodiin perustuvia projekteja:"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
msgctxt "@label"
msgid "Graphical user interface"
msgstr "Graafinen käyttöliittymä"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
msgctxt "@label"
msgid "Application framework"
msgstr "Sovelluskehys"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
msgctxt "@label"
msgid "G-code generator"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:138
msgctxt "@label"
msgid "Interprocess communication library"
msgstr "Prosessien välinen tietoliikennekirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
msgctxt "@label"
msgid "Programming language"
msgstr "Ohjelmointikieli"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
msgctxt "@label"
msgid "GUI framework"
msgstr "GUI-kehys"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
msgctxt "@label"
msgid "GUI framework bindings"
msgstr "GUI-kehyksen sidonnat"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
msgctxt "@label"
msgid "C/C++ Binding library"
msgstr "C/C++ -sidontakirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
msgctxt "@label"
msgid "Data interchange format"
msgstr "Data Interchange Format"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
msgctxt "@label"
msgid "Support library for scientific computing"
msgstr "Tieteellisen laskennan tukikirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
msgctxt "@label"
msgid "Support library for faster math"
msgstr "Nopeamman laskennan tukikirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
msgctxt "@label"
msgid "Support library for handling STL files"
msgstr "STL-tiedostojen käsittelyn tukikirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
msgctxt "@label"
msgid "Support library for handling planar objects"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
msgctxt "@label"
msgid "Support library for handling triangular meshes"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
msgctxt "@label"
msgid "Support library for analysis of complex networks"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
msgctxt "@label"
msgid "Support library for handling 3MF files"
msgstr "Tukikirjasto 3MF-tiedostojen käsittelyyn"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
msgctxt "@label"
msgid "Support library for file metadata and streaming"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
msgctxt "@label"
msgid "Serial communication library"
msgstr "Sarjatietoliikennekirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
msgctxt "@label"
msgid "ZeroConf discovery library"
msgstr "ZeroConf-etsintäkirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
msgctxt "@label"
msgid "Polygon clipping library"
msgstr "Monikulmion leikkauskirjasto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:156
msgctxt "@Label"
msgid "Python HTTP library"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
msgctxt "@label"
msgid "Font"
msgstr "Fontti"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
msgctxt "@label"
msgid "SVG icons"
msgstr "SVG-kuvakkeet"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:160
msgctxt "@label"
msgid "Linux cross-distribution application deployment"
msgstr ""
@@ -4897,27 +4615,27 @@ msgctxt "@title:window"
msgid "Save Project"
msgstr "Tallenna projekti"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:138
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:177
msgctxt "@action:label"
msgid "Extruder %1"
msgstr "Suulake %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:192
msgctxt "@action:label"
msgid "%1 & material"
msgstr "%1 & materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:243
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:194
+msgctxt "@action:label"
+msgid "Material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:label"
msgid "Don't show project summary on save again"
msgstr "Älä näytä projektin yhteenvetoa tallennettaessa"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:262
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:302
msgctxt "@action:button"
msgid "Save"
msgstr "Tallenna"
@@ -4947,31 +4665,993 @@ msgctxt "@action:button"
msgid "Import models"
msgstr "Tuo mallit"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:210
-msgctxt "@option:check"
-msgid "See only current build plate"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
+msgctxt "@label"
+msgid "Empty"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:226
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
+msgctxt "@label"
+msgid "Add a printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:246
-msgctxt "@action:button"
-msgid "Arrange current build plate"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
+msgctxt "@label"
+msgid "Add a networked printer"
msgstr ""
-#: X3GWriter/plugin.json
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
+msgctxt "@label"
+msgid "Add a non-networked printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:70
+msgctxt "@label"
+msgid "Add printer by IP address"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:133
+msgctxt "@text"
+msgid "Place enter your printer's IP address."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:204
+msgctxt "@label"
+msgid "Could not connect to device."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:208
+msgctxt "@label"
+msgid "The printer at this address has not responded yet."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:240
+msgctxt "@label"
+msgid "This printer cannot be added because it's an unknown printer or it's not the host of a group."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:329
+msgctxt "@button"
+msgid "Back"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:342
+msgctxt "@button"
+msgid "Connect"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/FirstStartMachineActionsContent.qml:77
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:123
+msgctxt "@button"
+msgid "Next"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:23
+msgctxt "@label"
+msgid "User Agreement"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:56
+msgctxt "@button"
+msgid "Agree"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:70
+msgctxt "@button"
+msgid "Decline and close"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:24
+msgctxt "@label"
+msgid "Help us to improve Ultimaker Cura"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:57
+msgctxt "@text"
+msgid "Ultimaker Cura collects anonymous data to improve print quality and user experience, including:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:71
+msgctxt "@text"
+msgid "Machine types"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:77
+msgctxt "@text"
+msgid "Material usage"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:83
+msgctxt "@text"
+msgid "Number of slices"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:89
+msgctxt "@text"
+msgid "Print settings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:102
+msgctxt "@text"
+msgid "Data collected by Ultimaker Cura will not contain any personal information."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:103
+msgctxt "@text"
+msgid "More information"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WhatsNewContent.qml:24
+msgctxt "@label"
+msgid "What's new in Ultimaker Cura"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:42
+msgctxt "@label"
+msgid "There is no printer found over your network."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:179
+msgctxt "@label"
+msgid "Refresh"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:190
+msgctxt "@label"
+msgid "Add printer by IP"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:223
+msgctxt "@label"
+msgid "Troubleshooting"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:211
+msgctxt "@label"
+msgid "Printer name"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:224
+msgctxt "@text"
+msgid "Please give your printer a name"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:36
+msgctxt "@label"
+msgid "Ultimaker Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:77
+msgctxt "@text"
+msgid "The next generation 3D printing workflow"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:94
+msgctxt "@text"
+msgid "- Send print jobs to Ultimaker printers outside your local network"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:97
+msgctxt "@text"
+msgid "- Store your Ultimaker Cura settings in the cloud for use anywhere"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:100
+msgctxt "@text"
+msgid "- Get exclusive access to print profiles from leading brands"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:119
+msgctxt "@button"
+msgid "Finish"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:128
+msgctxt "@button"
+msgid "Create an account"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:29
+msgctxt "@label"
+msgid "Welcome to Ultimaker Cura"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:47
+msgctxt "@text"
+msgid ""
+"Please follow these steps to set up\n"
+"Ultimaker Cura. This will only take a few moments."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:58
+msgctxt "@button"
+msgid "Get started"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:27
+msgctxt "@info:tooltip"
+msgid "3D View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:40
+msgctxt "@info:tooltip"
+msgid "Front View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
+msgctxt "@info:tooltip"
+msgid "Top View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
+msgctxt "@info:tooltip"
+msgid "Left View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:79
+msgctxt "@info:tooltip"
+msgid "Right View"
+msgstr ""
+
+#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
+msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
msgstr ""
-#: X3GWriter/plugin.json
+#: MachineSettingsAction/plugin.json
msgctxt "name"
-msgid "X3GWriter"
+msgid "Machine Settings action"
+msgstr "Laitteen asetukset -toiminto"
+
+#: Toolbox/plugin.json
+msgctxt "description"
+msgid "Find, manage and install new Cura packages."
msgstr ""
+#: Toolbox/plugin.json
+msgctxt "name"
+msgid "Toolbox"
+msgstr ""
+
+#: XRayView/plugin.json
+msgctxt "description"
+msgid "Provides the X-Ray view."
+msgstr "Näyttää kerrosnäkymän."
+
+#: XRayView/plugin.json
+msgctxt "name"
+msgid "X-Ray View"
+msgstr "Kerrosnäkymä"
+
+#: X3DReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading X3D files."
+msgstr "Tukee X3D-tiedostojen lukemista."
+
+#: X3DReader/plugin.json
+msgctxt "name"
+msgid "X3D Reader"
+msgstr "X3D-lukija"
+
+#: GCodeWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a file."
+msgstr ""
+
+#: GCodeWriter/plugin.json
+msgctxt "name"
+msgid "G-code Writer"
+msgstr ""
+
+#: ModelChecker/plugin.json
+msgctxt "description"
+msgid "Checks models and print configuration for possible printing issues and give suggestions."
+msgstr ""
+
+#: ModelChecker/plugin.json
+msgctxt "name"
+msgid "Model Checker"
+msgstr ""
+
+#: FirmwareUpdater/plugin.json
+msgctxt "description"
+msgid "Provides a machine actions for updating firmware."
+msgstr ""
+
+#: FirmwareUpdater/plugin.json
+msgctxt "name"
+msgid "Firmware Updater"
+msgstr ""
+
+#: AMFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading AMF files."
+msgstr ""
+
+#: AMFReader/plugin.json
+msgctxt "name"
+msgid "AMF Reader"
+msgstr ""
+
+#: USBPrinting/plugin.json
+msgctxt "description"
+msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
+msgstr "Hyväksyy GCode-määrittelyt ja lähettää ne tulostimeen. Lisäosa voi myös päivittää laiteohjelmiston."
+
+#: USBPrinting/plugin.json
+msgctxt "name"
+msgid "USB printing"
+msgstr "USB-tulostus"
+
+#: GCodeGzWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a compressed archive."
+msgstr ""
+
+#: GCodeGzWriter/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Writer"
+msgstr ""
+
+#: UFPWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing Ultimaker Format Packages."
+msgstr ""
+
+#: UFPWriter/plugin.json
+msgctxt "name"
+msgid "UFP Writer"
+msgstr ""
+
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr ""
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr ""
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "description"
+msgid "Provides removable drive hotplugging and writing support."
+msgstr "Tukee irrotettavan aseman kytkemistä lennossa ja sille kirjoittamista."
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "name"
+msgid "Removable Drive Output Device Plugin"
+msgstr "Irrotettavan aseman tulostusvälineen laajennus"
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "description"
+msgid "Manages network connections to Ultimaker networked printers."
+msgstr ""
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "name"
+msgid "Ultimaker Network Connection"
+msgstr ""
+
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr ""
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr ""
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "description"
+msgid "Checks for firmware updates."
+msgstr "Tarkistaa laiteohjelmistopäivitykset."
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "name"
+msgid "Firmware Update Checker"
+msgstr "Laiteohjelmiston päivitysten tarkistus"
+
+#: SimulationView/plugin.json
+msgctxt "description"
+msgid "Provides the Simulation view."
+msgstr ""
+
+#: SimulationView/plugin.json
+msgctxt "name"
+msgid "Simulation View"
+msgstr ""
+
+#: GCodeGzReader/plugin.json
+msgctxt "description"
+msgid "Reads g-code from a compressed archive."
+msgstr ""
+
+#: GCodeGzReader/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Reader"
+msgstr ""
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "description"
+msgid "Extension that allows for user created scripts for post processing"
+msgstr "Lisäosa, jonka avulla käyttäjät voivat luoda komentosarjoja jälkikäsittelyä varten"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "name"
+msgid "Post Processing"
+msgstr "Jälkikäsittely"
+
+#: SupportEraser/plugin.json
+msgctxt "description"
+msgid "Creates an eraser mesh to block the printing of support in certain places"
+msgstr ""
+
+#: SupportEraser/plugin.json
+msgctxt "name"
+msgid "Support Eraser"
+msgstr ""
+
+#: UFPReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading Ultimaker Format Packages."
+msgstr ""
+
+#: UFPReader/plugin.json
+msgctxt "name"
+msgid "UFP Reader"
+msgstr ""
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "description"
+msgid "Submits anonymous slice info. Can be disabled through preferences."
+msgstr "Lähettää anonyymiä viipalointitietoa. Voidaan lisäasetuksista kytkeä pois käytöstä."
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "name"
+msgid "Slice info"
+msgstr "Viipalointitiedot"
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "description"
+msgid "Provides capabilities to read and write XML-based material profiles."
+msgstr "Mahdollistaa XML-pohjaisten materiaaliprofiilien lukemisen ja kirjoittamisen."
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "name"
+msgid "Material Profiles"
+msgstr "Materiaaliprofiilit"
+
+#: LegacyProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from legacy Cura versions."
+msgstr "Tukee profiilien tuontia aikaisemmista Cura-versioista."
+
+#: LegacyProfileReader/plugin.json
+msgctxt "name"
+msgid "Legacy Cura Profile Reader"
+msgstr "Aikaisempien Cura-profiilien lukija"
+
+#: GCodeProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from g-code files."
+msgstr "Tukee profiilien tuontia GCode-tiedostoista."
+
+#: GCodeProfileReader/plugin.json
+msgctxt "name"
+msgid "G-code Profile Reader"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.2 to 3.3"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.3 to 3.4"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.3 to Cura 4.4."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.3 to 4.4"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
+msgstr "Päivittää kokoonpanon versiosta Cura 2.5 versioon Cura 2.6."
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.5 to 2.6"
+msgstr "Päivitys versiosta 2.5 versioon 2.6"
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
+msgstr "Päivittää kokoonpanon versiosta Cura 2.7 versioon Cura 3.0."
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.7 to 3.0"
+msgstr "Päivitys versiosta 2.7 versioon 3.0"
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.5 to Cura 4.0."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.5 to 4.0"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.4 to 3.5"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.0 to Cura 4.1."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.0 to 4.1"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.0 to 3.1"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.1 to Cura 4.2."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.1 to 4.2"
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
+msgstr "Päivittää kokoonpanon versiosta Cura 2.6 versioon Cura 2.7."
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.6 to 2.7"
+msgstr "Päivitys versiosta 2.6 versioon 2.7"
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
+msgstr "Päivittää kokoonpanon versiosta Cura 2.1 versioon Cura 2.2."
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.1 to 2.2"
+msgstr "Päivitys versiosta 2.1 versioon 2.2"
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
+msgstr "Päivittää kokoonpanon versiosta Cura 2.2 versioon Cura 2.4."
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.2 to 2.4"
+msgstr "Päivitys versiosta 2.2 versioon 2.4"
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.2 to Cura 4.3."
+msgstr ""
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.2 to 4.3"
+msgstr ""
+
+#: ImageReader/plugin.json
+msgctxt "description"
+msgid "Enables ability to generate printable geometry from 2D image files."
+msgstr "Mahdollistaa tulostettavien geometrioiden luomisen 2D-kuvatiedostoista."
+
+#: ImageReader/plugin.json
+msgctxt "name"
+msgid "Image Reader"
+msgstr "Kuvanlukija"
+
+#: TrimeshReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading model files."
+msgstr ""
+
+#: TrimeshReader/plugin.json
+msgctxt "name"
+msgid "Trimesh Reader"
+msgstr ""
+
+#: CuraEngineBackend/plugin.json
+msgctxt "description"
+msgid "Provides the link to the CuraEngine slicing backend."
+msgstr "Linkki CuraEngine-viipalointiin taustalla."
+
+#: CuraEngineBackend/plugin.json
+msgctxt "name"
+msgid "CuraEngine Backend"
+msgstr "CuraEngine-taustaosa"
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "description"
+msgid "Provides the Per Model Settings."
+msgstr "Mallikohtaisten asetusten muokkaus."
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "name"
+msgid "Per Model Settings Tool"
+msgstr "Mallikohtaisten asetusten työkalu"
+
+#: 3MFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading 3MF files."
+msgstr "Tukee 3MF-tiedostojen lukemista."
+
+#: 3MFReader/plugin.json
+msgctxt "name"
+msgid "3MF Reader"
+msgstr "3MF-lukija"
+
+#: SolidView/plugin.json
+msgctxt "description"
+msgid "Provides a normal solid mesh view."
+msgstr "Näyttää normaalin kiinteän verkkonäkymän."
+
+#: SolidView/plugin.json
+msgctxt "name"
+msgid "Solid View"
+msgstr "Kiinteä näkymä"
+
+#: GCodeReader/plugin.json
+msgctxt "description"
+msgid "Allows loading and displaying G-code files."
+msgstr "Mahdollistaa GCode-tiedostojen lataamisen ja näyttämisen."
+
+#: GCodeReader/plugin.json
+msgctxt "name"
+msgid "G-code Reader"
+msgstr "GCode-lukija"
+
+#: CuraDrive/plugin.json
+msgctxt "description"
+msgid "Backup and restore your configuration."
+msgstr ""
+
+#: CuraDrive/plugin.json
+msgctxt "name"
+msgid "Cura Backups"
+msgstr ""
+
+#: CuraProfileWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for exporting Cura profiles."
+msgstr "Tukee Cura-profiilien vientiä."
+
+#: CuraProfileWriter/plugin.json
+msgctxt "name"
+msgid "Cura Profile Writer"
+msgstr "Cura-profiilin kirjoitin"
+
+#: 3MFWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing 3MF files."
+msgstr "Tukee 3MF-tiedostojen kirjoittamista."
+
+#: 3MFWriter/plugin.json
+msgctxt "name"
+msgid "3MF Writer"
+msgstr "3MF-kirjoitin"
+
+#: PreviewStage/plugin.json
+msgctxt "description"
+msgid "Provides a preview stage in Cura."
+msgstr ""
+
+#: PreviewStage/plugin.json
+msgctxt "name"
+msgid "Preview Stage"
+msgstr ""
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "description"
+msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
+msgstr ""
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "name"
+msgid "Ultimaker machine actions"
+msgstr "Ultimaker-laitteen toiminnot"
+
+#: CuraProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing Cura profiles."
+msgstr "Tukee Cura-profiilien tuontia."
+
+#: CuraProfileReader/plugin.json
+msgctxt "name"
+msgid "Cura Profile Reader"
+msgstr "Cura-profiilin lukija"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Flatten active settings"
+#~ msgstr "Aktivoitujen asetusten tasoitus"
+
+#~ msgctxt "@info:status"
+#~ msgid "Profile has been flattened & activated."
+#~ msgstr "Profiili on tasoitettu ja aktivoitu."
+
+#~ msgctxt "X3G Writer File Description"
+#~ msgid "X3G File"
+#~ msgstr "X3G-tiedosto"
+
+#~ msgctxt "@action:button"
+#~ msgid "Retry"
+#~ msgstr "Yritä uudelleen"
+
+#~ msgctxt "@action:ComboBox option"
+#~ msgid "Update existing"
+#~ msgstr "Päivitä nykyinen"
+
+#~ msgctxt "@label"
+#~ msgid "Please select any upgrades made to this Ultimaker 2."
+#~ msgstr "Valitse tähän Ultimaker 2 -laitteeseen tehdyt päivitykset."
+
+#~ msgctxt "@label"
+#~ msgid "Olsson Block"
+#~ msgstr "Olsson Block -lämmitysosa"
+
+#~ msgctxt "@label"
+#~ msgid "Layer Height"
+#~ msgstr "Kerroksen korkeus"
+
+#~ msgctxt "@title:settings"
+#~ msgid "&Profile"
+#~ msgstr "&Profiili"
+
+#~ msgctxt "description"
+#~ msgid "Dump the contents of all settings to a HTML file."
+#~ msgstr "Vedosta kaikkien asetusten sisällöt HTML-tiedostoon."
+
+#~ msgctxt "name"
+#~ msgid "God Mode"
+#~ msgstr "Jumala-tila"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network."
+#~ msgstr "Yhdistetty verkon kautta tulostimeen."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. Please approve the access request on the printer."
+#~ msgstr "Yhdistetty verkon kautta. Hyväksy tulostimen käyttöoikeuspyyntö."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. No access to control the printer."
+#~ msgstr "Yhdistetty verkon kautta tulostimeen. Ei käyttöoikeutta tulostimen hallintaan."
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer requested. Please approve the request on the printer"
+#~ msgstr "Tulostimen käyttöoikeutta pyydetty. Hyväksy tulostimen pyyntö"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Re-send the access request"
+#~ msgstr "Lähetä käyttöoikeuspyyntö uudelleen"
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer accepted"
+#~ msgstr "Tulostimen käyttöoikeus hyväksytty"
+
+#~ msgctxt "@info:status"
+#~ msgid "No access to print with this printer. Unable to send print job."
+#~ msgstr "Tällä tulostimella tulostukseen ei ole käyttöoikeutta. Tulostustyön lähetys ei onnistu."
+
+#~ msgctxt "@action:button"
+#~ msgid "Request Access"
+#~ msgstr "Pyydä käyttöoikeutta"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Send access request to the printer"
+#~ msgstr "Lähetä tulostimen käyttöoikeuspyyntö"
+
+#~ msgctxt "@window:title"
+#~ msgid "Mismatched configuration"
+#~ msgstr "Ristiriitainen määritys"
+
+#~ msgctxt "@label"
+#~ msgid "Are you sure you wish to print with the selected configuration?"
+#~ msgstr "Haluatko varmasti tulostaa valitulla määrityksellä?"
+
+#~ msgctxt "@label"
+#~ msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Tulostimen ja Curan määrityksen tai kalibroinnin välillä on ristiriita. Parhaat tulokset saavutetaan viipaloimalla aina tulostimeen asetetuille PrintCoreille ja materiaaleille."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
+#~ msgstr "Uusien töiden lähettäminen (tilapäisesti) estetty, edellistä tulostustyötä lähetetään vielä."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to printer"
+#~ msgstr "Lähetetään tietoja tulostimeen"
+
+#~ msgctxt "@info:title"
+#~ msgid "Sending Data"
+#~ msgstr "Lähetetään tietoja"
+
+#~ msgctxt "@label"
+#~ msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
+#~ msgstr "Eri materiaali (Cura: {0}, tulostin: {1}) valittu suulakkeelle {2}"
+
+#~ msgctxt "@window:title"
+#~ msgid "Sync with your printer"
+#~ msgstr "Synkronoi tulostimen kanssa"
+
+#~ msgctxt "@label"
+#~ msgid "Would you like to use your current printer configuration in Cura?"
+#~ msgstr "Haluatko käyttää nykyistä tulostimen määritystä Curassa?"
+
+#~ msgctxt "@label"
+#~ msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Tulostimen PrintCoret tai materiaalit eivät vastaa tulostettavan projektin asetuksia. Parhaat tulokset saavutetaan viipaloimalla aina tulostimeen asetetuille PrintCoreille ja materiaaleille."
+
+#~ msgctxt "@info:status"
+#~ msgid "Printer '{printer_name}' has finished printing '{job_name}'."
+#~ msgstr "{printer_name} on tulostanut työn '{job_name}'."
+
+#~ msgctxt "@info:status"
+#~ msgid "Print finished"
+#~ msgstr "Tulosta valmis"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Connect to a printer"
+#~ msgstr "Yhdistä tulostimeen"
+
+#~ msgctxt "name"
+#~ msgid "UM3 Network Connection"
+#~ msgstr "UM3-verkkoyhteys"
+
+#~ msgctxt "@label"
+#~ msgid ""
+#~ "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
+#~ "\n"
+#~ "Select your printer from the list below:"
+#~ msgstr ""
+#~ "Tulosta suoraan tulostimeen verkon kautta yhdistämällä tulostin verkkoon verkkokaapelilla tai yhdistämällä tulostin Wi-Fi-verkkoon. Jos Curaa ei yhdistetä tulostimeen, GCode-tiedostot voidaan silti siirtää tulostimeen USB-aseman avulla.\n"
+#~ "\n"
+#~ "Valitse tulostin alla olevasta luettelosta:"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Show Changelog"
+#~ msgstr "Näytä muutosloki"
+
+#~ msgctxt "@info:title"
+#~ msgid "Collecting Data"
+#~ msgstr "Kerätään tietoja"
+
+#~ msgctxt "@title"
+#~ msgid "Machine Settings"
+#~ msgstr "Laitteen asetukset"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Settings"
+#~ msgstr "Tulostimen asetukset"
+
+#~ msgctxt "@option:check"
+#~ msgid "Origin at center"
+#~ msgstr "Alkukohta keskellä"
+
+#~ msgctxt "@option:check"
+#~ msgid "Heated bed"
+#~ msgstr "Lämmitettävä pöytä"
+
+#~ msgctxt "@label"
+#~ msgid "Printhead Settings"
+#~ msgstr "Tulostuspään asetukset"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Etäisyys tulostuspään vasemmalta puolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Etäisyys tulostuspään etupuolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Etäisyys tulostuspään oikealta puolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Etäisyys tulostuspään takapuolelta suuttimen keskikohtaan. Käytetään estämään aiempien tulosteiden ja tulostuspään yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
+
+#~ msgctxt "@label"
+#~ msgid "Gantry height"
+#~ msgstr "Korokkeen korkeus"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
+#~ msgstr "Suuttimen kärjen ja korokejärjestelmän (X- ja Y-akselit) välinen korkeusero. Käytetään estämään aiempien tulosteiden ja korokkeen yhteentörmäyksiä, kun tulostetaan yksi kerrallaan."
+
+#~ msgctxt "@label"
+#~ msgid "Nozzle Settings"
+#~ msgstr "Suutinasetukset"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
+#~ msgstr "Tulostimen tukema tulostuslangan nimellinen halkaisija. Materiaali ja/tai profiili korvaa tarkan halkaisijan."
+
+#~ msgctxt "@label"
+#~ msgid "Changelog"
+#~ msgstr "Muutosloki"
+
+#~ msgctxt "@alabel"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Anna verkon tulostimen IP-osoite tai isäntänimi."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
+#~ msgstr "Oletuksena valkoiset pikselit edustavat verkossa korkeita pisteitä ja mustat pikselit edustavat verkossa matalia pisteitä. Muuta asetus, jos haluat, että mustat pikselit edustavat verkossa korkeita pisteitä ja valkoiset pikselit edustavat verkossa matalia pisteitä."
+
+#~ msgctxt "@title"
+#~ msgid "Select Printer Upgrades"
+#~ msgstr "Valitse tulostimen päivitykset"
+
+#~ msgctxt "@label"
+#~ msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
+#~ msgstr "Valitse tukena käytettävä suulakepuristin. Näin mallin alle rakennetaan tukirakenteita estämään mallin painuminen tai tulostuminen ilmaan."
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Unable to Slice"
+#~ msgstr "Viipalointi ei onnistu"
+
+#~ msgctxt "@action:button"
+#~ msgid "Add Printer"
+#~ msgstr "Lisää tulostin"
+
#~ msgid "Modify G-Code"
#~ msgstr "Muokkaa GCode-arvoa"
@@ -5061,7 +5741,7 @@ msgstr ""
#~ msgctxt "@label:textbox"
#~ msgid "Search..."
-#~ msgstr "Haku…"
+#~ msgstr "Haku..."
#~ msgctxt "@label:listbox"
#~ msgid "Print Setup"
@@ -5163,34 +5843,6 @@ msgstr ""
#~ msgid "Click to check the material compatibility on Ultimaker.com."
#~ msgstr "Napsauta ja tarkista materiaalin yhteensopivuus sivustolla Ultimaker.com."
-#~ msgctxt "name"
-#~ msgid "Machine Settings action"
-#~ msgstr "Laitteen asetukset -toiminto"
-
-#~ msgctxt "description"
-#~ msgid "Provides the X-Ray view."
-#~ msgstr "Näyttää kerrosnäkymän."
-
-#~ msgctxt "name"
-#~ msgid "X-Ray View"
-#~ msgstr "Kerrosnäkymä"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading X3D files."
-#~ msgstr "Tukee X3D-tiedostojen lukemista."
-
-#~ msgctxt "name"
-#~ msgid "X3D Reader"
-#~ msgstr "X3D-lukija"
-
-#~ msgctxt "description"
-#~ msgid "Dump the contents of all settings to a HTML file."
-#~ msgstr "Vedosta kaikkien asetusten sisällöt HTML-tiedostoon."
-
-#~ msgctxt "name"
-#~ msgid "God Mode"
-#~ msgstr "Jumala-tila"
-
#~ msgctxt "description"
#~ msgid "Shows changes since latest checked version."
#~ msgstr "Näyttää viimeisimmän tarkistetun version jälkeen tapahtuneet muutokset."
@@ -5207,186 +5859,6 @@ msgstr ""
#~ msgid "Profile flatener"
#~ msgstr "Profiilin tasoitus"
-#~ msgctxt "description"
-#~ msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
-#~ msgstr "Hyväksyy GCode-määrittelyt ja lähettää ne tulostimeen. Lisäosa voi myös päivittää laiteohjelmiston."
-
-#~ msgctxt "name"
-#~ msgid "USB printing"
-#~ msgstr "USB-tulostus"
-
-#~ msgctxt "description"
-#~ msgid "Provides removable drive hotplugging and writing support."
-#~ msgstr "Tukee irrotettavan aseman kytkemistä lennossa ja sille kirjoittamista."
-
-#~ msgctxt "name"
-#~ msgid "Removable Drive Output Device Plugin"
-#~ msgstr "Irrotettavan aseman tulostusvälineen laajennus"
-
-#~ msgctxt "name"
-#~ msgid "UM3 Network Connection"
-#~ msgstr "UM3-verkkoyhteys"
-
-#~ msgctxt "description"
-#~ msgid "Checks for firmware updates."
-#~ msgstr "Tarkistaa laiteohjelmistopäivitykset."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Update Checker"
-#~ msgstr "Laiteohjelmiston päivitysten tarkistus"
-
-#~ msgctxt "description"
-#~ msgid "Extension that allows for user created scripts for post processing"
-#~ msgstr "Lisäosa, jonka avulla käyttäjät voivat luoda komentosarjoja jälkikäsittelyä varten"
-
-#~ msgctxt "name"
-#~ msgid "Post Processing"
-#~ msgstr "Jälkikäsittely"
-
-#~ msgctxt "description"
-#~ msgid "Submits anonymous slice info. Can be disabled through preferences."
-#~ msgstr "Lähettää anonyymiä viipalointitietoa. Voidaan lisäasetuksista kytkeä pois käytöstä."
-
-#~ msgctxt "name"
-#~ msgid "Slice info"
-#~ msgstr "Viipalointitiedot"
-
-#~ msgctxt "description"
-#~ msgid "Provides capabilities to read and write XML-based material profiles."
-#~ msgstr "Mahdollistaa XML-pohjaisten materiaaliprofiilien lukemisen ja kirjoittamisen."
-
-#~ msgctxt "name"
-#~ msgid "Material Profiles"
-#~ msgstr "Materiaaliprofiilit"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from legacy Cura versions."
-#~ msgstr "Tukee profiilien tuontia aikaisemmista Cura-versioista."
-
-#~ msgctxt "name"
-#~ msgid "Legacy Cura Profile Reader"
-#~ msgstr "Aikaisempien Cura-profiilien lukija"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from g-code files."
-#~ msgstr "Tukee profiilien tuontia GCode-tiedostoista."
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
-#~ msgstr "Päivittää kokoonpanon versiosta Cura 2.5 versioon Cura 2.6."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.5 to 2.6"
-#~ msgstr "Päivitys versiosta 2.5 versioon 2.6"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
-#~ msgstr "Päivittää kokoonpanon versiosta Cura 2.7 versioon Cura 3.0."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.7 to 3.0"
-#~ msgstr "Päivitys versiosta 2.7 versioon 3.0"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
-#~ msgstr "Päivittää kokoonpanon versiosta Cura 2.6 versioon Cura 2.7."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.6 to 2.7"
-#~ msgstr "Päivitys versiosta 2.6 versioon 2.7"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
-#~ msgstr "Päivittää kokoonpanon versiosta Cura 2.1 versioon Cura 2.2."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.1 to 2.2"
-#~ msgstr "Päivitys versiosta 2.1 versioon 2.2"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
-#~ msgstr "Päivittää kokoonpanon versiosta Cura 2.2 versioon Cura 2.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.2 to 2.4"
-#~ msgstr "Päivitys versiosta 2.2 versioon 2.4"
-
-#~ msgctxt "description"
-#~ msgid "Enables ability to generate printable geometry from 2D image files."
-#~ msgstr "Mahdollistaa tulostettavien geometrioiden luomisen 2D-kuvatiedostoista."
-
-#~ msgctxt "name"
-#~ msgid "Image Reader"
-#~ msgstr "Kuvanlukija"
-
-#~ msgctxt "description"
-#~ msgid "Provides the link to the CuraEngine slicing backend."
-#~ msgstr "Linkki CuraEngine-viipalointiin taustalla."
-
-#~ msgctxt "name"
-#~ msgid "CuraEngine Backend"
-#~ msgstr "CuraEngine-taustaosa"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Per Model Settings."
-#~ msgstr "Mallikohtaisten asetusten muokkaus."
-
-#~ msgctxt "name"
-#~ msgid "Per Model Settings Tool"
-#~ msgstr "Mallikohtaisten asetusten työkalu"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading 3MF files."
-#~ msgstr "Tukee 3MF-tiedostojen lukemista."
-
-#~ msgctxt "name"
-#~ msgid "3MF Reader"
-#~ msgstr "3MF-lukija"
-
-#~ msgctxt "description"
-#~ msgid "Provides a normal solid mesh view."
-#~ msgstr "Näyttää normaalin kiinteän verkkonäkymän."
-
-#~ msgctxt "name"
-#~ msgid "Solid View"
-#~ msgstr "Kiinteä näkymä"
-
-#~ msgctxt "description"
-#~ msgid "Allows loading and displaying G-code files."
-#~ msgstr "Mahdollistaa GCode-tiedostojen lataamisen ja näyttämisen."
-
-#~ msgctxt "name"
-#~ msgid "G-code Reader"
-#~ msgstr "GCode-lukija"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for exporting Cura profiles."
-#~ msgstr "Tukee Cura-profiilien vientiä."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Writer"
-#~ msgstr "Cura-profiilin kirjoitin"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing 3MF files."
-#~ msgstr "Tukee 3MF-tiedostojen kirjoittamista."
-
-#~ msgctxt "name"
-#~ msgid "3MF Writer"
-#~ msgstr "3MF-kirjoitin"
-
-#~ msgctxt "name"
-#~ msgid "Ultimaker machine actions"
-#~ msgstr "Ultimaker-laitteen toiminnot"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing Cura profiles."
-#~ msgstr "Tukee Cura-profiilien tuontia."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Reader"
-#~ msgstr "Cura-profiilin lukija"
-
#~ msgctxt "@action"
#~ msgid "Upgrade Firmware"
#~ msgstr "Päivitä laiteohjelmisto"
@@ -5517,7 +5989,7 @@ msgstr ""
#~ msgctxt "@title:menu menubar:file"
#~ msgid "Save &As..."
-#~ msgstr "Tallenna &nimellä…"
+#~ msgstr "Tallenna &nimellä..."
#~ msgctxt "description"
#~ msgid "Accepts G-Code and sends them over WiFi to a Doodle3D WiFi-Box."
diff --git a/resources/i18n/fi_FI/fdmextruder.def.json.po b/resources/i18n/fi_FI/fdmextruder.def.json.po
index f5ce73790d..86dd3b3474 100644
--- a/resources/i18n/fi_FI/fdmextruder.def.json.po
+++ b/resources/i18n/fi_FI/fdmextruder.def.json.po
@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
"PO-Revision-Date: 2017-08-11 14:31+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
diff --git a/resources/i18n/fi_FI/fdmprinter.def.json.po b/resources/i18n/fi_FI/fdmprinter.def.json.po
index 3bb377fe22..3f1b71753b 100644
--- a/resources/i18n/fi_FI/fdmprinter.def.json.po
+++ b/resources/i18n/fi_FI/fdmprinter.def.json.po
@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
"PO-Revision-Date: 2017-09-27 12:27+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
@@ -210,6 +210,16 @@ msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
msgstr "Sisältääkö laite lämmitettävän alustan."
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume label"
+msgid "Has Build Volume Temperature Stabilization"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume description"
+msgid "Whether the machine is able to stabilize the build volume temperature."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
@@ -232,7 +242,7 @@ msgstr "Suulakeryhmien määrä. Suulakeryhmä on syöttölaitteen, Bowden-putke
#: fdmprinter.def.json
msgctxt "extruders_enabled_count label"
-msgid "Number of Extruders that are enabled"
+msgid "Number of Extruders That Are Enabled"
msgstr ""
#: fdmprinter.def.json
@@ -242,8 +252,8 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
-msgid "Outer nozzle diameter"
-msgstr "Suuttimen ulkoläpimitta"
+msgid "Outer Nozzle Diameter"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter description"
@@ -252,8 +262,8 @@ msgstr "Suuttimen kärjen ulkoläpimitta."
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
-msgstr "Suuttimen pituus"
+msgid "Nozzle Length"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance description"
@@ -262,8 +272,8 @@ msgstr "Suuttimen kärjen ja tulostuspään alimman osan välinen korkeusero."
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
-msgstr "Suuttimen kulma"
+msgid "Nozzle Angle"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle description"
@@ -272,8 +282,8 @@ msgstr "Vaakatason ja suuttimen kärjen yllä olevan kartiomaisen osan välinen
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length label"
-msgid "Heat zone length"
-msgstr "Lämpöalueen pituus"
+msgid "Heat Zone Length"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length description"
@@ -302,8 +312,8 @@ msgstr "Lämpötilan hallinta Curan kautta. Kytke tämä pois, niin voit hallita
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed label"
-msgid "Heat up speed"
-msgstr "Lämpenemisnopeus"
+msgid "Heat Up Speed"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed description"
@@ -312,8 +322,8 @@ msgstr "Nopeus (°C/s), jolla suutin lämpenee, mitattuna keskiarvona normaaleis
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed label"
-msgid "Cool down speed"
-msgstr "Jäähdytysnopeus"
+msgid "Cool Down Speed"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed description"
@@ -332,7 +342,7 @@ msgstr "Minimiaika, jonka suulakkeen on oltava ei-aktiivinen, ennen kuin suutin
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
+msgid "G-code Flavor"
msgstr ""
#: fdmprinter.def.json
@@ -397,8 +407,8 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
-msgstr "Kielletyt alueet"
+msgid "Disallowed Areas"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas description"
@@ -417,8 +427,8 @@ msgstr "Monikulmioluettelo, jossa on alueet, joihin suutin ei saa siirtyä."
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
-msgstr "Laiteen pään monikulmio"
+msgid "Machine Head Polygon"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_head_polygon description"
@@ -427,8 +437,8 @@ msgstr "2D-siluetti tulostuspäästä (tuulettimen kannattimet pois lukien)"
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
-msgid "Machine head & Fan polygon"
-msgstr "Laiteen pään ja tuulettimen monikulmio"
+msgid "Machine Head & Fan Polygon"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon description"
@@ -437,8 +447,8 @@ msgstr "2D-siluetti tulostuspäästä (tuulettimen päät mukaan lukien)"
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
-msgstr "Korokkeen korkeus"
+msgid "Gantry Height"
+msgstr ""
#: fdmprinter.def.json
msgctxt "gantry_height description"
@@ -467,8 +477,8 @@ msgstr "Suuttimen sisäläpimitta. Muuta tätä asetusta, kun käytössä on muu
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label"
-msgid "Offset With Extruder"
-msgstr "Suulakkeen siirtymä"
+msgid "Offset with Extruder"
+msgstr ""
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords description"
@@ -1015,6 +1025,16 @@ msgctxt "bottom_layers description"
msgid "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number."
msgstr "Alakerrosten lukumäärä. Kun se lasketaan alaosan paksuudesta, arvo pyöristetään kokonaislukuun."
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers label"
+msgid "Initial Bottom Layers"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers description"
+msgid "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
@@ -1265,6 +1285,56 @@ msgctxt "z_seam_type option sharpest_corner"
msgid "Sharpest Corner"
msgstr "Terävin kulma"
+#: fdmprinter.def.json
+msgctxt "z_seam_position label"
+msgid "Z Seam Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position description"
+msgid "The position near where to start printing each part in a layer."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backleft"
+msgid "Back Left"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option back"
+msgid "Back"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backright"
+msgid "Back Right"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option right"
+msgid "Right"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontright"
+msgid "Front Right"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option front"
+msgid "Front"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontleft"
+msgid "Front Left"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option left"
+msgid "Left"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "z_seam_x label"
msgid "Z Seam X"
@@ -1292,8 +1362,8 @@ msgstr "Saumakulmien asetus"
#: fdmprinter.def.json
msgctxt "z_seam_corner description"
-msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
-msgstr "Määritä, vaikuttavatko mallin ulkolinjan kulmat sauman sijaintiin. Ei mitään tarkoittaa, että kulmilla ei ole vaikutusta sauman sijaintiin. Piilota sauma -valinnalla sauman sijainti sisäkulmassa on todennäköisempää. Paljasta sauma -valinnalla sauman sijainti ulkokulmassa on todennäköisempää. Piilota tai paljasta sauma -valinnalla sauman sijainti sisä- tai ulkokulmassa on todennäköisempää."
+msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner. Smart Hiding allows both inside and outside corners, but chooses inside corners more frequently, if appropriate."
+msgstr ""
#: fdmprinter.def.json
msgctxt "z_seam_corner option z_seam_corner_none"
@@ -1315,6 +1385,11 @@ msgctxt "z_seam_corner option z_seam_corner_any"
msgid "Hide or Expose Seam"
msgstr "Piilota tai paljasta sauma"
+#: fdmprinter.def.json
+msgctxt "z_seam_corner option z_seam_corner_weighted"
+msgid "Smart Hiding"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "z_seam_relative label"
msgid "Z Seam Relative"
@@ -1327,13 +1402,13 @@ msgstr "Kun tämä on käytössä, Z-sauman koordinaatit ovat suhteessa kunkin o
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic label"
-msgid "Ignore Small Z Gaps"
-msgstr "Ohita pienet Z-raot"
+msgid "No Skin in Z Gaps"
+msgstr ""
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic description"
-msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
-msgstr "Kun mallissa on pieniä pystyrakoja, ylä- ja alapuolen pintakalvon tekemiseen näihin kapeisiin paikkoihin voi kulua noin 5 % ylimääräistä laskenta-aikaa. Poista siinä tapauksessa tämä asetus käytöstä."
+msgid "When the model has small vertical gaps of only a few layers, there should normally be skin around those layers in the narrow space. Enable this setting to not generate skin if the vertical gap is very small. This improves printing time and slicing time, but technically leaves infill exposed to the air."
+msgstr ""
#: fdmprinter.def.json
msgctxt "skin_outline_count label"
@@ -1352,8 +1427,8 @@ msgstr "Ota silitys käyttöön"
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
-msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
-msgstr "Yläpinnan läpikäynti yhden ylimääräisen kerran ilman materiaalin pursotusta. Tämän tarkoitus on sulattaa yläosan muovia enemmän, jolloin saadaan sileämpi pinta."
+msgid "Go over the top surface one additional time, but this time extruding very little material. This is meant to melt the plastic on top further, creating a smoother surface. The pressure in the nozzle chamber is kept high so that the creases in the surface are filled with material."
+msgstr ""
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
@@ -1445,6 +1520,26 @@ msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
msgstr "Silityksen aikainen nopeuden hetkellinen maksimimuutos."
+#: fdmprinter.def.json
+msgctxt "skin_overlap label"
+msgid "Skin Overlap Percentage"
+msgstr "Pintakalvon limityksen prosentti"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm label"
+msgid "Skin Overlap"
+msgstr "Pintakalvon limitys"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "infill label"
msgid "Infill"
@@ -1610,6 +1705,16 @@ msgctxt "infill_offset_y description"
msgid "The infill pattern is moved this distance along the Y axis."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location label"
+msgid "Randomize Infill Start"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location description"
+msgid "Randomize which infill line is printed first. This prevents one segment becoming the strongest, but it does so at the cost of an additional travel move."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "infill_multiplier label"
msgid "Infill Line Multiplier"
@@ -1662,26 +1767,6 @@ msgctxt "infill_overlap_mm description"
msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
msgstr "Limityksen määrä täytön ja seinämien välillä. Pienellä limityksellä seinämät liittyvät tukevasti täyttöön."
-#: fdmprinter.def.json
-msgctxt "skin_overlap label"
-msgid "Skin Overlap Percentage"
-msgstr "Pintakalvon limityksen prosentti"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm label"
-msgid "Skin Overlap"
-msgstr "Pintakalvon limitys"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "infill_wipe_dist label"
msgid "Infill Wipe Distance"
@@ -1862,6 +1947,16 @@ msgctxt "default_material_print_temperature description"
msgid "The default temperature used for printing. This should be the \"base\" temperature of a material. All other print temperatures should use offsets based on this value"
msgstr "Tulostuksessa käytettävä oletuslämpötila. Tämän tulee olla materiaalin ”pohjalämpötila”. Kaikkien muiden tulostuslämpötilojen tulee käyttää tähän arvoon perustuvia siirtymiä."
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature label"
+msgid "Build Volume Temperature"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature description"
+msgid "The temperature of the environment to print in. If this is 0, the build volume temperature will not be adjusted."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
msgid "Printing Temperature"
@@ -1972,6 +2067,86 @@ msgctxt "material_shrinkage_percentage description"
msgid "Shrinkage ratio in percentage."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "material_crystallinity label"
+msgid "Crystalline Material"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_crystallinity description"
+msgid "Is this material the type that breaks off cleanly when heated (crystalline), or is it the type that produces long intertwined polymer chains (non-crystalline)?"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position label"
+msgid "Anti-ooze Retracted Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position description"
+msgid "How far the material needs to be retracted before it stops oozing."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed label"
+msgid "Anti-ooze Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed description"
+msgid "How fast the material needs to be retracted during a filament switch to prevent oozing."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position label"
+msgid "Break Preparation Retracted Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position description"
+msgid "How far the filament can be stretched before it breaks, while heated."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed label"
+msgid "Break Preparation Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed description"
+msgid "How fast the filament needs to be retracted just before breaking it off in a retraction."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position label"
+msgid "Break Retracted Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position description"
+msgid "How far to retract the filament in order to break it cleanly."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed label"
+msgid "Break Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed description"
+msgid "The speed at which to retract the filament in order to break it cleanly."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature label"
+msgid "Break Temperature"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature description"
+msgid "The temperature at which the filament is broken for a clean break."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "material_flow label"
msgid "Flow"
@@ -1982,6 +2157,126 @@ msgctxt "material_flow description"
msgid "Flow compensation: the amount of material extruded is multiplied by this value."
msgstr "Virtauksen kompensointi: pursotetun materiaalin määrä kerrotaan tällä arvolla."
+#: fdmprinter.def.json
+msgctxt "wall_material_flow label"
+msgid "Wall Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_material_flow description"
+msgid "Flow compensation on wall lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow label"
+msgid "Outer Wall Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow description"
+msgid "Flow compensation on the outermost wall line."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow label"
+msgid "Inner Wall(s) Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow description"
+msgid "Flow compensation on wall lines for all wall lines except the outermost one."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow label"
+msgid "Top/Bottom Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow description"
+msgid "Flow compensation on top/bottom lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow label"
+msgid "Top Surface Skin Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow description"
+msgid "Flow compensation on lines of the areas at the top of the print."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow label"
+msgid "Infill Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow description"
+msgid "Flow compensation on infill lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow label"
+msgid "Skirt/Brim Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow description"
+msgid "Flow compensation on skirt or brim lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow label"
+msgid "Support Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow description"
+msgid "Flow compensation on support structure lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow label"
+msgid "Support Interface Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow description"
+msgid "Flow compensation on lines of support roof or floor."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow label"
+msgid "Support Roof Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow description"
+msgid "Flow compensation on support roof lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow label"
+msgid "Support Floor Flow"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow description"
+msgid "Flow compensation on support floor lines."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow label"
+msgid "Prime Tower Flow"
+msgstr "Esitäyttötornin virtaus"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow description"
+msgid "Flow compensation on prime tower lines."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "material_flow_layer_0 label"
msgid "Initial Layer Flow"
@@ -2099,7 +2394,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "limit_support_retractions description"
-msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure."
msgstr ""
#: fdmprinter.def.json
@@ -2152,6 +2447,16 @@ msgctxt "switch_extruder_prime_speed description"
msgid "The speed at which the filament is pushed back after a nozzle switch retraction."
msgstr "Nopeus, jolla tulostuslanka työnnetään takaisin suuttimen vaihdon takaisinvedon jälkeen."
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount label"
+msgid "Nozzle Switch Extra Prime Amount"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount description"
+msgid "Extra material to prime after nozzle switching."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "speed label"
msgid "Speed"
@@ -2343,14 +2648,14 @@ msgid "The speed at which the skirt and brim are printed. Normally this is done
msgstr "Nopeus, jolla helma ja reunus tulostetaan. Yleensä se tehdään alkukerroksen nopeudella. Joskus helma tai reunus halutaan kuitenkin tulostaa eri nopeudella."
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override label"
-msgid "Maximum Z Speed"
-msgstr "Z:n maksiminopeus"
+msgctxt "speed_z_hop label"
+msgid "Z Hop Speed"
+msgstr ""
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override description"
-msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
-msgstr "Maksiminopeus, jolla alustaa liikutetaan. Jos tämä määritetään nollaan, tulostuksessa käytetään laiteohjelmiston oletusasetuksia Z:n maksiminopeudelle."
+msgctxt "speed_z_hop description"
+msgid "The speed at which the vertical Z movement is made for Z Hops. This is typically lower than the print speed since the build plate or machine's gantry is harder to move."
+msgstr ""
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers label"
@@ -2852,16 +3157,6 @@ msgctxt "travel_avoid_distance description"
msgid "The distance between the nozzle and already printed parts when avoiding during travel moves."
msgstr "Suuttimen ja aiemmin tulostetun osan välinen etäisyys siirtoliikkeiden yhteydessä."
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position label"
-msgid "Start Layers with the Same Part"
-msgstr "Aloita kerrokset samalla osalla"
-
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position description"
-msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
-msgstr "Aloita tulostus jokaisessa kerroksessa tulostamalla kappale, joka on lähellä samaa pistettä, jotta uutta kerrosta ei aloiteta tulostamalla kappaletta, johon edellinen kerros päättyi. Näin saadaan aikaan paremmat ulokkeet ja pienet osat, mutta tulostus kestää kauemmin."
-
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
@@ -2922,6 +3217,16 @@ msgctxt "retraction_hop_after_extruder_switch description"
msgid "After the machine switched from one extruder to the other, the build plate is lowered to create clearance between the nozzle and the print. This prevents the nozzle from leaving oozed material on the outside of a print."
msgstr "Alustaa lasketaan koneen vaihdettua yhdestä suulakkeesta toiseen, jotta suuttimen ja tulosteen väliin jää tilaa. Tämä estää suutinta jättämästä tihkunutta ainetta tulosteen ulkopuolelle."
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height label"
+msgid "Z Hop After Extruder Switch Height"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height description"
+msgid "The height difference when performing a Z Hop after extruder switch."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "cooling label"
msgid "Cooling"
@@ -3192,6 +3497,11 @@ msgctxt "support_pattern option cross"
msgid "Cross"
msgstr "Risti"
+#: fdmprinter.def.json
+msgctxt "support_pattern option gyroid"
+msgid "Gyroid"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_wall_count label"
msgid "Support Wall Line Count"
@@ -3253,13 +3563,13 @@ msgid "Distance between the printed initial layer support structure lines. This
msgstr ""
#: fdmprinter.def.json
-msgctxt "support_infill_angle label"
-msgid "Support Infill Line Direction"
+msgctxt "support_infill_angles label"
+msgid "Support Infill Line Directions"
msgstr ""
#: fdmprinter.def.json
-msgctxt "support_infill_angle description"
-msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
+msgctxt "support_infill_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees."
msgstr ""
#: fdmprinter.def.json
@@ -3389,8 +3699,8 @@ msgstr "Tuen liitosetäisyys"
#: fdmprinter.def.json
msgctxt "support_join_distance description"
-msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
-msgstr "Tukirakenteiden maksimietäisyys toisistaan X-/Y-suunnissa. Kun erilliset rakenteet ovat tätä arvoa lähempänä toisiaan, rakenteet sulautuvat toisiinsa."
+msgid "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one."
+msgstr ""
#: fdmprinter.def.json
msgctxt "support_offset label"
@@ -3674,7 +3984,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "minimum_interface_area description"
-msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
+msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will be printed as normal support."
msgstr ""
#: fdmprinter.def.json
@@ -3684,7 +3994,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "minimum_roof_area description"
-msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
+msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will be printed as normal support."
msgstr ""
#: fdmprinter.def.json
@@ -3694,7 +4004,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "minimum_bottom_area description"
-msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
+msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will be printed as normal support."
msgstr ""
#: fdmprinter.def.json
@@ -3727,6 +4037,36 @@ msgctxt "support_bottom_offset description"
msgid "Amount of offset applied to the floors of the support."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "support_interface_angles label"
+msgid "Support Interface Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles label"
+msgid "Support Roof Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles label"
+msgid "Support Floor Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -3768,14 +4108,14 @@ msgid "The diameter of a special tower."
msgstr "Erityistornin läpimitta."
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter label"
-msgid "Minimum Diameter"
-msgstr "Minimiläpimitta"
+msgctxt "support_tower_maximum_supported_diameter label"
+msgid "Maximum Tower-Supported Diameter"
+msgstr ""
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter description"
-msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
-msgstr "Erityisellä tukitornilla tuettavan pienen alueen minimiläpimitta X- ja Y-suunnissa."
+msgctxt "support_tower_maximum_supported_diameter description"
+msgid "Maximum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+msgstr ""
#: fdmprinter.def.json
msgctxt "support_tower_roof_angle label"
@@ -4269,16 +4609,6 @@ msgctxt "prime_tower_enable description"
msgid "Print a tower next to the print which serves to prime the material after each nozzle switch."
msgstr "Tulosta tulosteen viereen torni, jolla materiaali esitäytetään aina suuttimen vaihdon jälkeen."
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular label"
-msgid "Circular Prime Tower"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular description"
-msgid "Make the prime tower as a circular shape."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
@@ -4319,16 +4649,6 @@ msgctxt "prime_tower_position_y description"
msgid "The y coordinate of the position of the prime tower."
msgstr "Esitäyttötornin sijainnin Y-koordinaatti."
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow label"
-msgid "Prime Tower Flow"
-msgstr "Esitäyttötornin virtaus"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow description"
-msgid "Flow compensation: the amount of material extruded is multiplied by this value."
-msgstr "Virtauksen kompensointi: pursotetun materiaalin määrä kerrotaan tällä arvolla."
-
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
@@ -4339,6 +4659,16 @@ msgctxt "prime_tower_wipe_enabled description"
msgid "After printing the prime tower with one nozzle, wipe the oozed material from the other nozzle off on the prime tower."
msgstr "Kun esitäyttötorni on tulostettu yhdellä suuttimella, pyyhi toisesta suuttimesta tihkunut materiaali pois esitäyttötornissa."
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable label"
+msgid "Prime Tower Brim"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable description"
+msgid "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
msgid "Enable Ooze Shield"
@@ -4459,6 +4789,36 @@ msgctxt "remove_empty_first_layers description"
msgid "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution label"
+msgid "Maximum Travel Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution description"
+msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation label"
+msgid "Maximum Deviation"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation description"
+msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "blackmagic label"
msgid "Special Modes"
@@ -4621,8 +4981,8 @@ msgstr "Kierukoitujen ääriviivojen tasoittaminen"
#: fdmprinter.def.json
msgctxt "smooth_spiralized_contours description"
-msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
-msgstr "Vähennä Z-sauman näkyvyyttä tasoittamalla kierukoidut ääriviivat (Z-sauman pitäisi olla lähes näkymätön tulosteessa, mutta kerrosnäkymässä sen voi edelleen havaita). Ota huomioon, että tasoittaminen usein sumentaa pinnan pieniä yksityiskohtia."
+msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+msgstr ""
#: fdmprinter.def.json
msgctxt "relative_extrusion label"
@@ -4834,26 +5194,6 @@ msgctxt "minimum_polygon_circumference description"
msgid "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution label"
-msgid "Maximum Travel Resolution"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution description"
-msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -4994,16 +5334,6 @@ msgctxt "coasting_speed description"
msgid "The speed by which to move during coasting, relative to the speed of the extrusion path. A value slightly under 100% is advised, since during the coasting move the pressure in the bowden tube drops."
msgstr "Nopeus, jolla siirrytään vapaaliu'un aikana, suhteessa pursotusreitin nopeuteen. Arvoksi suositellaan hieman alle 100 %, sillä vapaaliukusiirron aikana paine Bowden-putkessa laskee."
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation label"
-msgid "Alternate Skin Rotation"
-msgstr "Vuorottele pintakalvon pyöritystä"
-
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation description"
-msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
-msgstr "Muuttaa ylä-/alakerrosten tulostussuuntaa. Normaalisti ne tulostetaan vain vinottain. Tämä asetus lisää vain X- ja vain Y -suunnat."
-
#: fdmprinter.def.json
msgctxt "cross_infill_pocket_size label"
msgid "Cross 3D Pocket Size"
@@ -5111,8 +5441,8 @@ msgstr "Ota kartiomainen tuki käyttöön"
#: fdmprinter.def.json
msgctxt "support_conical_enabled description"
-msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
-msgstr "Kokeellinen ominaisuus: tekee tukialueet pienemmiksi alaosassa verrattuna ulokkeeseen."
+msgid "Make support areas smaller at the bottom than at the overhang."
+msgstr ""
#: fdmprinter.def.json
msgctxt "support_conical_angle label"
@@ -5176,22 +5506,22 @@ msgstr "Keskimääräinen etäisyys kunkin linjasegmentin satunnaisten pisteiden
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
-msgid "Flow rate compensation max extrusion offset"
+msgid "Flow Rate Compensation Max Extrusion Offset"
msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
-msgid "The maximum distance in mm to compensate."
+msgid "The maximum distance in mm to move the filament to compensate for changes in flow rate."
msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor label"
-msgid "Flow rate compensation factor"
+msgid "Flow Rate Compensation Factor"
msgstr ""
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor description"
-msgid "The multiplication factor for the flow rate -> distance translation."
+msgid "How far to move the filament in order to compensate for changes in flow rate, as a percentage of how far the filament would move in one second of extrusion."
msgstr ""
#: fdmprinter.def.json
@@ -5455,7 +5785,7 @@ msgstr "Suuttimen ja vaakasuoraan laskevien linjojen välinen etäisyys. Suuremp
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr ""
#: fdmprinter.def.json
@@ -5465,7 +5795,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation label"
-msgid "Adaptive layers maximum variation"
+msgid "Adaptive Layers Maximum Variation"
msgstr ""
#: fdmprinter.def.json
@@ -5475,7 +5805,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation_step label"
-msgid "Adaptive layers variation step size"
+msgid "Adaptive Layers Variation Step Size"
msgstr ""
#: fdmprinter.def.json
@@ -5485,12 +5815,12 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
+msgid "Adaptive Layers Topography Size"
msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold description"
-msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgid "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together."
msgstr ""
#: fdmprinter.def.json
@@ -5500,7 +5830,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "wall_overhang_angle description"
-msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
+msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging. Overhang that gets supported by support will not be treated as overhang either."
msgstr ""
#: fdmprinter.def.json
@@ -5703,6 +6033,196 @@ msgctxt "bridge_fan_speed_3 description"
msgid "Percentage fan speed to use when printing the third bridge skin layer."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "clean_between_layers label"
+msgid "Wipe Nozzle Between Layers"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "clean_between_layers description"
+msgid "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe label"
+msgid "Material Volume Between Wipes"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe description"
+msgid "Maximum material, that can be extruded before another nozzle wipe is initiated."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable label"
+msgid "Wipe Retraction Enable"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable description"
+msgid "Retract the filament when the nozzle is moving over a non-printed area."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount label"
+msgid "Wipe Retraction Distance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount description"
+msgid "Amount to retract the filament so it does not ooze during the wipe sequence."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount label"
+msgid "Wipe Retraction Extra Prime Amount"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount description"
+msgid "Some material can ooze away during a wipe travel moves, which can be compensated for here."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed label"
+msgid "Wipe Retraction Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed description"
+msgid "The speed at which the filament is retracted and primed during a wipe retraction move."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed label"
+msgid "Wipe Retraction Retract Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed description"
+msgid "The speed at which the filament is retracted during a wipe retraction move."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed label"
+msgid "Retraction Prime Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed description"
+msgid "The speed at which the filament is primed during a wipe retraction move."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause label"
+msgid "Wipe Pause"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause description"
+msgid "Pause after the unretract."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable label"
+msgid "Wipe Z Hop When Retracted"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable description"
+msgid "Whenever a retraction is done, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount label"
+msgid "Wipe Z Hop Height"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount description"
+msgid "The height difference when performing a Z Hop."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed label"
+msgid "Wipe Hop Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed description"
+msgid "Speed to move the z-axis during the hop."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x label"
+msgid "Wipe Brush X Position"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x description"
+msgid "X location where wipe script will start."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count label"
+msgid "Wipe Repeat Count"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count description"
+msgid "Number of times to move the nozzle across the brush."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance label"
+msgid "Wipe Move Distance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance description"
+msgid "The distance to move the head back and forth across the brush."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size label"
+msgid "Small Hole Max Size"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size description"
+msgid "Holes and part outlines with a diameter smaller than this will be printed using Small Feature Speed."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length label"
+msgid "Small Feature Max Length"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length description"
+msgid "Feature outlines that are shorter than this length will be printed using Small Feature Speed."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor label"
+msgid "Small Feature Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor description"
+msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 label"
+msgid "Small Feature Initial Layer Speed"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 description"
+msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5763,6 +6283,114 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Mallissa käytettävä muunnosmatriisi, kun malli ladataan tiedostosta."
+#~ msgctxt "skin_alternate_rotation label"
+#~ msgid "Alternate Skin Rotation"
+#~ msgstr "Vuorottele pintakalvon pyöritystä"
+
+#~ msgctxt "skin_alternate_rotation description"
+#~ msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
+#~ msgstr "Muuttaa ylä-/alakerrosten tulostussuuntaa. Normaalisti ne tulostetaan vain vinottain. Tämä asetus lisää vain X- ja vain Y -suunnat."
+
+#~ msgctxt "ironing_enabled description"
+#~ msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
+#~ msgstr "Yläpinnan läpikäynti yhden ylimääräisen kerran ilman materiaalin pursotusta. Tämän tarkoitus on sulattaa yläosan muovia enemmän, jolloin saadaan sileämpi pinta."
+
+#~ msgctxt "start_layers_at_same_position label"
+#~ msgid "Start Layers with the Same Part"
+#~ msgstr "Aloita kerrokset samalla osalla"
+
+#~ msgctxt "start_layers_at_same_position description"
+#~ msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
+#~ msgstr "Aloita tulostus jokaisessa kerroksessa tulostamalla kappale, joka on lähellä samaa pistettä, jotta uutta kerrosta ei aloiteta tulostamalla kappaletta, johon edellinen kerros päättyi. Näin saadaan aikaan paremmat ulokkeet ja pienet osat, mutta tulostus kestää kauemmin."
+
+#~ msgctxt "z_seam_corner description"
+#~ msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
+#~ msgstr "Määritä, vaikuttavatko mallin ulkolinjan kulmat sauman sijaintiin. Ei mitään tarkoittaa, että kulmilla ei ole vaikutusta sauman sijaintiin. Piilota sauma -valinnalla sauman sijainti sisäkulmassa on todennäköisempää. Paljasta sauma -valinnalla sauman sijainti ulkokulmassa on todennäköisempää. Piilota tai paljasta sauma -valinnalla sauman sijainti sisä- tai ulkokulmassa on todennäköisempää."
+
+#~ msgctxt "skin_no_small_gaps_heuristic label"
+#~ msgid "Ignore Small Z Gaps"
+#~ msgstr "Ohita pienet Z-raot"
+
+#~ msgctxt "skin_no_small_gaps_heuristic description"
+#~ msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
+#~ msgstr "Kun mallissa on pieniä pystyrakoja, ylä- ja alapuolen pintakalvon tekemiseen näihin kapeisiin paikkoihin voi kulua noin 5 % ylimääräistä laskenta-aikaa. Poista siinä tapauksessa tämä asetus käytöstä."
+
+#~ msgctxt "max_feedrate_z_override label"
+#~ msgid "Maximum Z Speed"
+#~ msgstr "Z:n maksiminopeus"
+
+#~ msgctxt "max_feedrate_z_override description"
+#~ msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
+#~ msgstr "Maksiminopeus, jolla alustaa liikutetaan. Jos tämä määritetään nollaan, tulostuksessa käytetään laiteohjelmiston oletusasetuksia Z:n maksiminopeudelle."
+
+#~ msgctxt "support_join_distance description"
+#~ msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
+#~ msgstr "Tukirakenteiden maksimietäisyys toisistaan X-/Y-suunnissa. Kun erilliset rakenteet ovat tätä arvoa lähempänä toisiaan, rakenteet sulautuvat toisiinsa."
+
+#~ msgctxt "support_minimal_diameter label"
+#~ msgid "Minimum Diameter"
+#~ msgstr "Minimiläpimitta"
+
+#~ msgctxt "support_minimal_diameter description"
+#~ msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+#~ msgstr "Erityisellä tukitornilla tuettavan pienen alueen minimiläpimitta X- ja Y-suunnissa."
+
+#~ msgctxt "prime_tower_flow description"
+#~ msgid "Flow compensation: the amount of material extruded is multiplied by this value."
+#~ msgstr "Virtauksen kompensointi: pursotetun materiaalin määrä kerrotaan tällä arvolla."
+
+#~ msgctxt "smooth_spiralized_contours description"
+#~ msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+#~ msgstr "Vähennä Z-sauman näkyvyyttä tasoittamalla kierukoidut ääriviivat (Z-sauman pitäisi olla lähes näkymätön tulosteessa, mutta kerrosnäkymässä sen voi edelleen havaita). Ota huomioon, että tasoittaminen usein sumentaa pinnan pieniä yksityiskohtia."
+
+#~ msgctxt "support_conical_enabled description"
+#~ msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
+#~ msgstr "Kokeellinen ominaisuus: tekee tukialueet pienemmiksi alaosassa verrattuna ulokkeeseen."
+
+#~ msgctxt "machine_nozzle_tip_outer_diameter label"
+#~ msgid "Outer nozzle diameter"
+#~ msgstr "Suuttimen ulkoläpimitta"
+
+#~ msgctxt "machine_nozzle_head_distance label"
+#~ msgid "Nozzle length"
+#~ msgstr "Suuttimen pituus"
+
+#~ msgctxt "machine_nozzle_expansion_angle label"
+#~ msgid "Nozzle angle"
+#~ msgstr "Suuttimen kulma"
+
+#~ msgctxt "machine_heat_zone_length label"
+#~ msgid "Heat zone length"
+#~ msgstr "Lämpöalueen pituus"
+
+#~ msgctxt "machine_nozzle_heat_up_speed label"
+#~ msgid "Heat up speed"
+#~ msgstr "Lämpenemisnopeus"
+
+#~ msgctxt "machine_nozzle_cool_down_speed label"
+#~ msgid "Cool down speed"
+#~ msgstr "Jäähdytysnopeus"
+
+#~ msgctxt "machine_disallowed_areas label"
+#~ msgid "Disallowed areas"
+#~ msgstr "Kielletyt alueet"
+
+#~ msgctxt "machine_head_polygon label"
+#~ msgid "Machine head polygon"
+#~ msgstr "Laiteen pään monikulmio"
+
+#~ msgctxt "machine_head_with_fans_polygon label"
+#~ msgid "Machine head & Fan polygon"
+#~ msgstr "Laiteen pään ja tuulettimen monikulmio"
+
+#~ msgctxt "gantry_height label"
+#~ msgid "Gantry height"
+#~ msgstr "Korokkeen korkeus"
+
+#~ msgctxt "machine_use_extruder_offset_to_offset_coords label"
+#~ msgid "Offset With Extruder"
+#~ msgstr "Suulakkeen siirtymä"
+
#~ msgctxt "skin_overlap_mm description"
#~ msgid "The amount of overlap between the skin and the walls. A slight overlap allows the walls to connect firmly to the skin."
#~ msgstr "Limityksen määrä pintakalvon ja seinämien välillä. Pienellä limityksellä seinämät liittyvät tukevasti pintakalvoon."
diff --git a/resources/i18n/fr_FR/cura.po b/resources/i18n/fr_FR/cura.po
index f7f48e9410..3633753794 100644
--- a/resources/i18n/fr_FR/cura.po
+++ b/resources/i18n/fr_FR/cura.po
@@ -5,20 +5,20 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
-"PO-Revision-Date: 2018-09-28 14:59+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: French\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: French , French \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.2.3\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr "Paramètres de la machine"
@@ -40,13 +40,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr "Fichier GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr "GCodeWriter ne prend pas en charge le mode non-texte."
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr "Veuillez préparer le G-Code avant d'exporter."
@@ -56,7 +56,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "Assistant de modèle 3D"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -68,73 +68,52 @@ msgstr ""
"
Un ou plusieurs modèles 3D peuvent ne pas s'imprimer de manière optimale en raison de la taille du modèle et de la configuration matérielle :
\n"
"
{model_names}
\n"
"
Découvrez comment optimiser la qualité et la fiabilité de l'impression.
"
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
msgctxt "@action"
msgid "Update Firmware"
msgstr "Mettre à jour le firmware"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
-msgctxt "@item:inmenu"
-msgid "Flatten active settings"
-msgstr "Aplatir les paramètres actifs"
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "Fichier AMF"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:35
-msgctxt "@info:status"
-msgid "Profile has been flattened & activated."
-msgstr "Le profil a été aplati et activé."
-
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:33
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Impression par USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:34
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:43
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Imprimer via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:35
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:44
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Imprimer via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:71
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:80
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Connecté via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:96
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:105
msgctxt "@label"
msgid "A USB print is in progress, closing Cura will stop this print. Are you sure?"
msgstr "Une impression USB est en cours, la fermeture de Cura arrêtera cette impression. Êtes-vous sûr ?"
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/install/X3GWriter/__init__.py:15
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
-msgctxt "X3G Writer File Description"
-msgid "X3G File"
-msgstr "Fichier X3G"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "A print is still in progress. Cura cannot start another print via USB until the previous print has completed."
+msgstr "Une impression est encore en cours. Cura ne peut pas démarrer une autre impression via USB tant que l'impression précédente n'est pas terminée."
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
-msgctxt "X3g Writer Plugin Description"
-msgid "Writes X3g to files"
-msgstr "Écrit X3G dans des fichiers"
-
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:21
-msgctxt "X3g Writer File Description"
-msgid "X3g File"
-msgstr "Fichier X3G"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "Print in Progress"
+msgstr "Impression en cours"
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
@@ -148,6 +127,7 @@ msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeGzWriter ne prend pas en charge le mode texte."
#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:28
+#: /home/ruben/Projects/Cura/plugins/UFPReader/__init__.py:22
msgctxt "@item:inlistbox"
msgid "Ultimaker Format Package"
msgstr "Ultimaker Format Package"
@@ -169,7 +149,7 @@ msgid "Save to Removable Drive {0}"
msgstr "Enregistrer sur un lecteur amovible {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:107
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "Aucun format de fichier n'est disponible pour écriture !"
@@ -206,10 +186,9 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "Impossible d'enregistrer sur le lecteur {0}: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:152
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1629
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:139
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1668
msgctxt "@info:title"
msgid "Error"
msgstr "Erreur"
@@ -238,9 +217,9 @@ msgstr "Ejecter le lecteur amovible {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:151
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:163
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1619
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1719
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1658
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1758
msgctxt "@info:title"
msgid "Warning"
msgstr "Avertissement"
@@ -267,337 +246,164 @@ msgctxt "@item:intext"
msgid "Removable Drive"
msgstr "Lecteur amovible"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:74
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py:26
+msgctxt "@action"
+msgid "Connect via Network"
+msgstr "Connecter via le réseau"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:57
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Imprimer sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:58
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Imprimer sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
-msgctxt "@info:status"
-msgid "Connected over the network."
-msgstr "Connecté sur le réseau."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
-msgctxt "@info:status"
-msgid "Connected over the network. Please approve the access request on the printer."
-msgstr "Connecté sur le réseau. Veuillez approuver la demande d'accès sur l'imprimante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:93
-msgctxt "@info:status"
-msgid "Connected over the network. No access to control the printer."
-msgstr "Connecté sur le réseau. Pas d'accès pour commander l'imprimante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
-msgctxt "@info:status"
-msgid "Access to the printer requested. Please approve the request on the printer"
-msgstr "Accès à l'imprimante demandé. Veuillez approuver la demande sur l'imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:101
-msgctxt "@info:title"
-msgid "Authentication status"
-msgstr "Statut d'authentification"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
-msgctxt "@info:title"
-msgid "Authentication Status"
-msgstr "Statut d'authentification"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:187
-msgctxt "@action:button"
-msgid "Retry"
-msgstr "Réessayer"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
-msgctxt "@info:tooltip"
-msgid "Re-send the access request"
-msgstr "Renvoyer la demande d'accès"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
-msgctxt "@info:status"
-msgid "Access to the printer accepted"
-msgstr "Accès à l'imprimante accepté"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
-msgctxt "@info:status"
-msgid "No access to print with this printer. Unable to send print job."
-msgstr "Aucun accès pour imprimer avec cette imprimante. Impossible d'envoyer la tâche d'impression."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:65
-msgctxt "@action:button"
-msgid "Request Access"
-msgstr "Demande d'accès"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:66
-msgctxt "@info:tooltip"
-msgid "Send access request to the printer"
-msgstr "Envoyer la demande d'accès à l'imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:201
-msgctxt "@label"
-msgid "Unable to start a new print job."
-msgstr "Impossible de démarrer une nouvelle tâche d'impression."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:203
-msgctxt "@label"
-msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
-msgstr "Un problème avec la configuration de votre Ultimaker empêche le démarrage de l'impression. Veuillez résoudre ce problème avant de continuer."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:209
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:231
-msgctxt "@window:title"
-msgid "Mismatched configuration"
-msgstr "Configuration différente"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:223
-msgctxt "@label"
-msgid "Are you sure you wish to print with the selected configuration?"
-msgstr "Êtes-vous sûr(e) de vouloir imprimer avec la configuration sélectionnée ?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:225
-msgctxt "@label"
-msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Problème de compatibilité entre la configuration ou l'étalonnage de l'imprimante et Cura. Pour un résultat optimal, découpez toujours pour les PrintCores et matériaux insérés dans votre imprimante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:252
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:162
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:162
-msgctxt "@info:status"
-msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
-msgstr "Envoi de nouvelles tâches (temporairement) bloqué, envoi de la tâche d'impression précédente en cours."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:180
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
-msgctxt "@info:status"
-msgid "Sending data to printer"
-msgstr "Envoi des données à l'imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:182
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:199
-msgctxt "@info:title"
-msgid "Sending Data"
-msgstr "Envoi des données"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:200
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:395
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:38
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:391
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:254
-msgctxt "@action:button"
-msgid "Cancel"
-msgstr "Annuler"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:324
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr "Pas de PrintCore inséré dans la fente {slot_number}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:330
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No material loaded in slot {slot_number}"
-msgstr "Aucun matériau inséré dans la fente {slot_number}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:353
-#, python-brace-format
-msgctxt "@label"
-msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
-msgstr "PrintCore différent (Cura : {cura_printcore_name}, Imprimante : {remote_printcore_name}) sélectionné pour l'extrudeuse {extruder_id}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:362
-#, python-brace-format
-msgctxt "@label"
-msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr "Matériau différent (Cura : {0}, Imprimante : {1}) sélectionné pour l'extrudeuse {2}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:548
-msgctxt "@window:title"
-msgid "Sync with your printer"
-msgstr "Synchroniser avec votre imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:550
-msgctxt "@label"
-msgid "Would you like to use your current printer configuration in Cura?"
-msgstr "Voulez-vous utiliser votre configuration d'imprimante actuelle dans Cura ?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:552
-msgctxt "@label"
-msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Les PrintCores et / ou matériaux sur votre imprimante diffèrent de ceux de votre projet actuel. Pour un résultat optimal, découpez toujours pour les PrintCores et matériaux insérés dans votre imprimante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:59
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Connecté sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:275
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:342
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:15
+msgctxt "@info:status"
+msgid "Please wait until the current job has been sent."
+msgstr "Veuillez patienter jusqu'à ce que la tâche en cours ait été envoyée."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:16
+msgctxt "@info:title"
+msgid "Print error"
+msgstr "Erreur d'impression"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:21
+msgctxt "@info:title"
+msgid "New cloud printers found"
+msgstr "Nouvelles imprimantes cloud trouvées"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:22
+msgctxt "@info:message"
+msgid "New printers have been found connected to your account, you can find them in your list of discovered printers."
+msgstr "De nouvelles imprimantes ont été trouvées connectées à votre compte. Vous pouvez les trouver dans votre liste d'imprimantes découvertes."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:27
+msgctxt "@info:option_text"
+msgid "Do not show this message again"
+msgstr "Ne plus afficher ce message"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:27
+#, python-brace-format
+msgctxt "@info:status"
+msgid "You are attempting to connect to {0} but it is not the host of a group. You can visit the web page to configure it as a group host."
+msgstr "Vous tentez de vous connecter à {0} mais ce n'est pas l'hôte de groupe. Vous pouvez visiter la page Web pour la configurer en tant qu'hôte de groupe."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:30
+msgctxt "@info:title"
+msgid "Not a group host"
+msgstr "Pas un hôte de groupe"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:35
+msgctxt "@action"
+msgid "Configure group"
+msgstr "Configurer le groupe"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:27
+msgctxt "@info:status"
+msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
+msgstr "Lancez et surveillez des impressions où que vous soyez avec votre compte Ultimaker."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:33
+msgctxt "@info:status Ultimaker Cloud should not be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Se connecter à Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:36
+msgctxt "@action"
+msgid "Get started"
+msgstr "Prise en main"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Lancement d'une tâche d'impression"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading print job to printer."
+msgstr "Téléchargement de la tâche d'impression sur l'imprimante."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:15
msgctxt "@info:status"
msgid "Print job was successfully sent to the printer."
msgstr "L'envoi de la tâche d'impression à l'imprimante a réussi."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:277
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:343
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:16
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Données envoyées"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:278
-msgctxt "@action:button"
-msgid "View in Monitor"
-msgstr "Afficher sur le moniteur"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:390
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:290
-#, python-brace-format
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:18
msgctxt "@info:status"
-msgid "Printer '{printer_name}' has finished printing '{job_name}'."
-msgstr "{printer_name} a terminé d'imprimer '{job_name}'."
+msgid "You are attempting to connect to a printer that is not running Ultimaker Connect. Please update the printer to the latest firmware."
+msgstr "Vous tentez de vous connecter à une imprimante qui n'exécute pas Ultimaker Connect. Veuillez mettre à jour l'imprimante avec le dernier micrologiciel."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:392
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:294
-#, python-brace-format
-msgctxt "@info:status"
-msgid "The print job '{job_name}' was finished."
-msgstr "La tâche d'impression '{job_name}' est terminée."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:393
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:289
-msgctxt "@info:status"
-msgid "Print finished"
-msgstr "Impression terminée"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:573
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:607
-msgctxt "@label:material"
-msgid "Empty"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:574
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:608
-msgctxt "@label:material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:151
-msgctxt "@action:button"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:152
-msgctxt "@properties:tooltip"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:153
-msgctxt "@info:status"
-msgid "Connected via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:163
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:21
msgctxt "@info:title"
-msgid "Cloud error"
-msgstr ""
+msgid "Update your printer"
+msgstr "Mettre à jour votre imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:180
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:24
+#, python-brace-format
msgctxt "@info:status"
-msgid "Could not export print job."
-msgstr ""
+msgid "Cura has detected material profiles that were not yet installed on the host printer of group {0}."
+msgstr "Cura a détecté des profils de matériau qui ne sont pas encore installés sur l'imprimante hôte du groupe {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:330
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:26
+msgctxt "@info:title"
+msgid "Sending materials to printer"
+msgstr "Envoi de matériaux à l'imprimante"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:15
msgctxt "@info:text"
msgid "Could not upload the data to the printer."
-msgstr ""
+msgstr "Impossible de transférer les données à l'imprimante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:16
+msgctxt "@info:title"
+msgid "Network error"
+msgstr "Erreur de réseau"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:27
msgctxt "@info:status"
msgid "tomorrow"
-msgstr ""
+msgstr "demain"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:30
msgctxt "@info:status"
msgid "today"
-msgstr ""
+msgstr "aujourd'hui"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:151
-msgctxt "@info:description"
-msgid "There was an error connecting to the cloud."
-msgstr ""
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:138
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Imprimer via le cloud"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:139
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Imprimer via le cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:140
msgctxt "@info:status"
-msgid "Sending data to remote cluster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:456
-msgctxt "@info:status"
-msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:460
-msgctxt "@info:status"
-msgid "Connect to Ultimaker Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:461
-msgctxt "@action"
-msgid "Don't ask me again for this printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:464
-msgctxt "@action"
-msgid "Get started"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:478
-msgctxt "@info:status"
-msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:482
-msgctxt "@info:status"
-msgid "Connected!"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:486
-msgctxt "@action"
-msgid "Review your connection"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
-msgctxt "@action"
-msgid "Connect via Network"
-msgstr "Connecter via le réseau"
+msgid "Connected via Cloud"
+msgstr "Connecté via le cloud"
#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Surveiller"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:124
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:125
msgctxt "@info"
msgid "Could not access update information."
msgstr "Impossible d'accéder aux informations de mise à jour."
@@ -624,12 +430,12 @@ msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Vue en couches"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:117
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Cura n'affiche pas les couches avec précision lorsque l'impression filaire est activée"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:118
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vue simulation"
@@ -637,12 +443,12 @@ msgstr "Vue simulation"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
msgctxt "@item:inmenu"
msgid "Post Processing"
-msgstr ""
+msgstr "Post-traitement"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
msgctxt "@item:inmenu"
msgid "Modify G-Code"
-msgstr ""
+msgstr "Modifier le G-Code"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12
msgctxt "@label"
@@ -654,46 +460,11 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr "Créer un volume dans lequel les supports ne sont pas imprimés."
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr "Cura recueille des statistiques d'utilisation anonymes."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:55
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Collecte des données"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:57
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Plus d'informations"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:58
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr "Voir plus d'informations sur les données envoyées par Cura."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:60
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Autoriser"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:61
-msgctxt "@action:tooltip"
-msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
-msgstr "Autoriser Cura à envoyer des statistiques d'utilisation anonymes pour mieux prioriser les améliorations futures apportées à Cura. Certaines de vos préférences et paramètres sont envoyés, ainsi que la version du logiciel Cura et un hachage des modèles que vous découpez."
-
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Profils Cura 15.04"
-#: /home/ruben/Projects/Cura/plugins/R2D2/__init__.py:17
-msgctxt "@item:inmenu"
-msgid "Evaluation"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/ImageReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "JPG Image"
@@ -719,56 +490,86 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Image GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:15
+msgctxt "@item:inlistbox 'Open' is part of the name of this file format."
+msgid "Open Compressed Triangle Mesh"
+msgstr "Ouvrir le maillage triangulaire compressé"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:19
+msgctxt "@item:inlistbox"
+msgid "COLLADA Digital Asset Exchange"
+msgstr "COLLADA Digital Asset Exchange"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:23
+msgctxt "@item:inlistbox"
+msgid "glTF Binary"
+msgstr "glTF binaire"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:27
+msgctxt "@item:inlistbox"
+msgid "glTF Embedded JSON"
+msgstr "JSON incorporé glTF"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:36
+msgctxt "@item:inlistbox"
+msgid "Stanford Triangle Format"
+msgstr "Format Triangle de Stanford"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:40
+msgctxt "@item:inlistbox"
+msgid "Compressed COLLADA Digital Asset Exchange"
+msgstr "COLLADA Digital Asset Exchange compressé"
+
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
msgctxt "@info:status"
msgid "Unable to slice with the current material as it is incompatible with the selected machine or configuration."
msgstr "Impossible de découper le matériau actuel, car celui-ci est incompatible avec la machine ou la configuration sélectionnée."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:389
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:398
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:407
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:416
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:362
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:386
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:395
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:404
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:413
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "Impossible de découper"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "Impossible de couper avec les paramètres actuels. Les paramètres suivants contiennent des erreurs : {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}"
msgstr "Impossible de couper en raison de certains paramètres par modèle. Les paramètres suivants contiennent des erreurs sur un ou plusieurs modèles : {error_labels}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:394
msgctxt "@info:status"
msgid "Unable to slice because the prime tower or prime position(s) are invalid."
msgstr "Impossible de couper car la tour primaire ou la (les) position(s) d'amorçage ne sont pas valides."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid "Unable to slice because there are objects associated with disabled Extruder %s."
msgstr "Impossible de couper car il existe des objets associés à l'extrudeuse désactivée %s."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:412
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume or are assigned to a disabled extruder. Please scale or rotate models to fit, or enable an extruder."
-msgstr ""
+msgstr "Rien à découper car les modèles ne conviennent pas au volume d'impression ou sont assignés à une extrudeuse désactivée. Mettez les modèles à l'échelle ou faites-les pivoter pour les faire correspondre, ou activez une extrudeuse."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Traitement des couches"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Informations"
@@ -783,12 +584,12 @@ msgctxt "@info:tooltip"
msgid "Configure Per Model Settings"
msgstr "Configurer les paramètres par modèle"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:186
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Recommandé"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:188
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personnalisé"
@@ -799,19 +600,19 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "Fichier 3MF"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:190
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:763
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:198
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:651
msgctxt "@label"
msgid "Nozzle"
msgstr "Buse"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:469
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:496
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Project file {0} contains an unknown machine type {1}. Cannot import the machine. Models will be imported instead."
msgstr "Le fichier projet {0} contient un type de machine inconnu {1}. Impossible d'importer la machine. Les modèles seront importés à la place."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:472
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:499
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Ouvrir un fichier de projet"
@@ -826,18 +627,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Fichier G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:324
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:335
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Analyse du G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:326
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:476
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:337
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:491
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Détails G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:474
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:489
msgctxt "@info:generic"
msgid "Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."
msgstr "Assurez-vous que le g-code est adapté à votre imprimante et à la configuration de l'imprimante avant d'y envoyer le fichier. La représentation du g-code peut ne pas être exacte."
@@ -845,7 +646,7 @@ msgstr "Assurez-vous que le g-code est adapté à votre imprimante et à la conf
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
msgctxt "@item:inmenu"
msgid "Manage backups"
-msgstr ""
+msgstr "Gérer les sauvegardes"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
@@ -858,32 +659,32 @@ msgstr "Sauvegarde"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
msgctxt "@info:backup_status"
msgid "There was an error listing your backups."
-msgstr ""
+msgstr "Une erreur s’est produite lors du listage de vos sauvegardes."
-#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:121
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:132
msgctxt "@info:backup_status"
msgid "There was an error trying to restore your backup."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la tentative de restauration de votre sauvegarde."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:15
msgctxt "@info:title"
msgid "Backups"
-msgstr ""
+msgstr "Sauvegardes"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
msgctxt "@info:backup_status"
msgid "Uploading your backup..."
-msgstr ""
+msgstr "Téléchargement de votre sauvegarde..."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:36
msgctxt "@info:backup_status"
msgid "There was an error while uploading your backup."
-msgstr ""
+msgstr "Une erreur s’est produite lors du téléchargement de votre sauvegarde."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:39
msgctxt "@info:backup_status"
msgid "Your backup has finished uploading."
-msgstr ""
+msgstr "Le téléchargement de votre sauvegarde est terminé."
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
@@ -891,16 +692,6 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Profil Cura"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
-msgctxt "@item:inmenu"
-msgid "Profile Assistant"
-msgstr "Assistant de profil"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
-msgctxt "@item:inlistbox"
-msgid "Profile Assistant"
-msgstr "Assistant de profil"
-
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:26
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -919,274 +710,364 @@ msgstr "Erreur d'écriture du fichier 3MF."
#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
msgctxt "@item:inmenu"
msgid "Preview"
-msgstr ""
+msgstr "Aperçu"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Sélectionner les mises à niveau"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
-msgctxt "@action"
-msgid "Checkup"
-msgstr "Check-up"
-
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
msgstr "Nivellement du plateau"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:81
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Paroi externe"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:82
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Parois internes"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:83
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Couche extérieure"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:84
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Remplissage"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:85
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Remplissage du support"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:86
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Interface du support"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:87
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Support"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:88
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Jupe"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Déplacement"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Rétractions"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Autre"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:309
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Fichier {0} prédécoupé"
-
-#: /home/ruben/Projects/Cura/cura/API/Account.py:77
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
msgctxt "@info:title"
msgid "Login failed"
msgstr "La connexion a échoué"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:201
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:36
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "Non pris en charge"
+
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:55
+msgctxt "@info:No intent profile selected"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:196
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:125
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Le fichier existe déjà"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:202
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:197
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:126
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Le fichier {0} existe déjà. Êtes-vous sûr de vouloir le remplacer ?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:425
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:428
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:433
msgctxt "@info:status"
msgid "Invalid file URL:"
-msgstr ""
+msgstr "URL de fichier invalide :"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:206
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "Pas écrasé"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:780
+msgctxt "@info:message Followed by a list of settings."
+msgid "Settings have been changed to match the current availability of extruders:"
+msgstr "Les paramètres ont été modifiés pour correspondre aux extrudeuses actuellement disponibles :"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:915
-#, python-format
-msgctxt "@info:generic"
-msgid "Settings have been changed to match the current availability of extruders: [%s]"
-msgstr "Les paramètres ont été modifiés pour correspondre aux extrudeuses actuellement disponibles : [%s]"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:917
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:782
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Paramètres mis à jour"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1458
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1334
msgctxt "@info:title"
msgid "Extruder(s) Disabled"
-msgstr ""
+msgstr "Extrudeuse(s) désactivée(s)"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1457
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:99
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:86
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:182
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:223
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Inconnu"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:137
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "Échec de l'exportation du profil vers {0} : {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:138
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "Échec de l'exportation du profil vers {0} : le plug-in du générateur a rapporté une erreur."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:149
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "Profil exporté vers {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:150
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "L'exportation a réussi"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr ""
-
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
-msgid "Can't import profile from {0} before a printer is added."
-msgstr ""
+msgid "Failed to import profile from {0}: {1}"
+msgstr "Impossible d'importer le profil depuis {0} : {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:181
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags !"
+msgid "Can't import profile from {0} before a printer is added."
+msgstr "Impossible d'importer le profil depuis {0} avant l'ajout d'une imprimante."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:198
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "No custom profile to import in file {0}"
msgstr "Aucun profil personnalisé à importer dans le fichier {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:202
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}:"
msgstr "Échec de l'importation du profil depuis le fichier {0} :"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:226
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:236
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "This profile {0} contains incorrect data, could not import it."
msgstr "Le profil {0} contient des données incorrectes ; échec de l'importation."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:241
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:325
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
-msgstr "La machine définie dans le profil {0} ({1}) ne correspond pas à votre machine actuelle ({2}) ; échec de l'importation."
-
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to import profile from {0}:"
msgstr "Échec de l'importation du profil depuis le fichier {0} :"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:328
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Importation du profil {0} réussie"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:319
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:331
#, python-brace-format
msgctxt "@info:status"
msgid "File {0} does not contain any valid profile."
msgstr "Le fichier {0} ne contient pas de profil valide."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:322
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:334
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "Le profil {0} est un type de fichier inconnu ou est corrompu."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:340
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:369
msgctxt "@label"
msgid "Custom profile"
msgstr "Personnaliser le profil"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:385
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "Il manque un type de qualité au profil."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:370
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:399
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "Impossible de trouver un type de qualité {0} pour la configuration actuelle."
-#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:69
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:76
+msgctxt "@tooltip"
+msgid "Outer Wall"
+msgstr "Paroi externe"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:77
+msgctxt "@tooltip"
+msgid "Inner Walls"
+msgstr "Parois internes"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:78
+msgctxt "@tooltip"
+msgid "Skin"
+msgstr "Couche extérieure"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:79
+msgctxt "@tooltip"
+msgid "Infill"
+msgstr "Remplissage"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:80
+msgctxt "@tooltip"
+msgid "Support Infill"
+msgstr "Remplissage du support"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:81
+msgctxt "@tooltip"
+msgid "Support Interface"
+msgstr "Interface du support"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:82
+msgctxt "@tooltip"
+msgid "Support"
+msgstr "Support"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:83
+msgctxt "@tooltip"
+msgid "Skirt"
+msgstr "Jupe"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:84
+msgctxt "@tooltip"
+msgid "Prime Tower"
+msgstr "Tour primaire"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:85
+msgctxt "@tooltip"
+msgid "Travel"
+msgstr "Déplacement"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:86
+msgctxt "@tooltip"
+msgid "Retractions"
+msgstr "Rétractions"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:87
+msgctxt "@tooltip"
+msgid "Other"
+msgstr "Autre"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:302
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "Fichier {0} prédécoupé"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Suivant"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:62
#, python-brace-format
msgctxt "@label"
msgid "Group #{group_nr}"
msgstr "Groupe nº {group_nr}"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:65
-msgctxt "@info:title"
-msgid "Network enabled printers"
-msgstr "Imprimantes réseau"
+#: /home/ruben/Projects/Cura/cura/UI/WhatsNewPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:169
+msgctxt "@action:button"
+msgid "Close"
+msgstr "Fermer"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:80
-msgctxt "@info:title"
-msgid "Local printers"
-msgstr "Imprimantes locales"
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Ajouter"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:18
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:352
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:58
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:149
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:406
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:294
+msgctxt "@action:button"
+msgid "Cancel"
+msgstr "Annuler"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:36
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:320
+msgctxt "@label"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:39
+msgctxt "@label"
+msgid "Visual"
+msgstr "Visuel"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:40
+msgctxt "@text"
+msgid "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality."
+msgstr "Le profil visuel est conçu pour imprimer des prototypes et des modèles visuels dans le but d'obtenir une qualité visuelle et de surface élevée."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:43
+msgctxt "@label"
+msgid "Engineering"
+msgstr "Engineering"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:44
+msgctxt "@text"
+msgid "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances."
+msgstr "Le profil d'ingénierie est conçu pour imprimer des prototypes fonctionnels et des pièces finales dans le but d'obtenir une meilleure précision et des tolérances"
+" plus étroites."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:47
+msgctxt "@label"
+msgid "Draft"
+msgstr "Ébauche"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:48
+msgctxt "@text"
+msgid "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction."
+msgstr "L'ébauche du profil est conçue pour imprimer les prototypes initiaux et la validation du concept dans le but de réduire considérablement le temps d'impression."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr "Pas écrasé"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:357
+msgctxt "@label"
+msgid "Custom profiles"
+msgstr "Personnaliser les profils"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:391
#, python-brace-format
msgctxt "@item:inlistbox"
msgid "All Supported Types ({0})"
msgstr "Tous les types supportés ({0})"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:110
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:392
msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Tous les fichiers (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:665
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:213
msgctxt "@label"
msgid "Custom Material"
msgstr "Matériau personnalisé"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:666
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:256
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:214
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:205
msgctxt "@label"
msgid "Custom"
msgstr "Personnalisé"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:116
+msgctxt "@label"
+msgid "The printer(s) below cannot be connected because they are part of a group"
+msgstr "Les imprimantes ci-dessous ne peuvent pas être connectées car elles font partie d'un groupe"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:118
+msgctxt "@label"
+msgid "Available networked printers"
+msgstr "Imprimantes en réseau disponibles"
+
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:90
msgctxt "@info:status"
msgid "The build volume height has been reduced due to the value of the \"Print Sequence\" setting to prevent the gantry from colliding with printed models."
msgstr "La hauteur du volume d'impression a été réduite en raison de la valeur du paramètre « Séquence d'impression » afin d'éviter que le portique ne heurte les modèles imprimés."
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:83
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:92
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volume d'impression"
@@ -1201,52 +1082,67 @@ msgctxt "@info:backup_failed"
msgid "Tried to restore a Cura backup without having proper data or meta data."
msgstr "A essayé de restaurer une sauvegarde Cura sans disposer de données ou de métadonnées appropriées."
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:124
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:125
msgctxt "@info:backup_failed"
-msgid "Tried to restore a Cura backup that does not match your current version."
-msgstr "A essayé de restaurer une sauvegarde Cura qui ne correspond pas à votre version actuelle."
+msgid "Tried to restore a Cura backup that is higher than the current version."
+msgstr "A essayé de restaurer une sauvegarde Cura supérieure à la version actuelle."
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr "Impossible de lire la réponse."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
msgctxt "@info"
msgid "Unable to reach the Ultimaker account server."
-msgstr ""
+msgstr "Impossible d’atteindre le serveur du compte Ultimaker."
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:70
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr "Veuillez donner les permissions requises lors de l'autorisation de cette application."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:77
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
+msgstr "Une erreur s'est produite lors de la connexion, veuillez réessayer."
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:29
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Multiplication et placement d'objets"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:30
msgctxt "@info:title"
msgid "Placing Objects"
-msgstr ""
+msgstr "Placement des objets"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:149
msgctxt "@info:status"
msgid "Unable to find a location within the build volume for all objects"
msgstr "Impossible de trouver un emplacement dans le volume d'impression pour tous les objets"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Placement de l'objet"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:30
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:67
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:66
msgctxt "@info:status"
msgid "Finding new location for objects"
msgstr "Recherche d'un nouvel emplacement pour les objets"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:34
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:71
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:70
msgctxt "@info:title"
msgid "Finding Location"
msgstr "Recherche d'emplacement"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Impossible de trouver un emplacement"
@@ -1377,242 +1273,205 @@ msgstr "Journaux"
#: /home/ruben/Projects/Cura/cura/CrashHandler.py:322
msgctxt "@title:groupbox"
-msgid "User description"
-msgstr "Description de l'utilisateur"
+msgid "User description (Note: Developers may not speak your language, please use English if possible)"
+msgstr "Description de l'utilisateur (Remarque : les développeurs peuvent ne pas partler votre langue. Veuillez utiliser l'anglais si possible)"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:341
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Envoyer rapport"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:480
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:513
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Chargement des machines..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:781
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:520
+msgctxt "@info:progress"
+msgid "Setting up preferences..."
+msgstr "Configuration des préférences..."
+
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:824
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Préparation de la scène..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:817
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:859
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Chargement de l'interface..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1059
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1150
#, python-format
msgctxt "@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm."
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr "%(width).1f x %(depth).1f x %(height).1f mm"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1618
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1657
#, python-brace-format
msgctxt "@info:status"
msgid "Only one G-code file can be loaded at a time. Skipped importing {0}"
msgstr "Un seul fichier G-Code peut être chargé à la fois. Importation de {0} sautée"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1628
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1667
#, python-brace-format
msgctxt "@info:status"
msgid "Can't open any other file if G-code is loading. Skipped importing {0}"
msgstr "Impossible d'ouvrir un autre fichier si le G-Code est en cours de chargement. Importation de {0} sautée"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1718
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1757
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "Le modèle sélectionné était trop petit pour être chargé."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:62
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Paramètres de la machine"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:81
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:100
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:56
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Paramètres de l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:70
msgctxt "@label"
msgid "X (Width)"
msgstr "X (Largeur)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:112
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:122
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:132
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:387
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:429
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:441
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:897
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:74
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:88
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:102
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:243
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:265
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:285
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:79
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:93
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:109
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:124
msgctxt "@label"
msgid "mm"
msgstr "mm"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:84
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (Profondeur)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:98
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (Hauteur)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:143
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:112
msgctxt "@label"
msgid "Build plate shape"
msgstr "Forme du plateau"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:152
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:125
+msgctxt "@label"
msgid "Origin at center"
msgstr "Origine au centre"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:160
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:137
+msgctxt "@label"
msgid "Heated bed"
msgstr "Plateau chauffant"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:171
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:149
+msgctxt "@label"
+msgid "Heated build volume"
+msgstr "Volume de fabrication chauffant"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:161
msgctxt "@label"
msgid "G-code flavor"
msgstr "Parfum G-Code"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:184
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:185
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Paramètres de la tête d'impression"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:199
msgctxt "@label"
msgid "X min"
msgstr "X min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:195
-msgctxt "@tooltip"
-msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distance entre la gauche de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:219
msgctxt "@label"
msgid "Y min"
msgstr "Y min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:205
-msgctxt "@tooltip"
-msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distance entre le devant de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:239
msgctxt "@label"
msgid "X max"
msgstr "X max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:215
-msgctxt "@tooltip"
-msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distance entre la droite de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:261
msgctxt "@label"
msgid "Y max"
msgstr "Y max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:225
-msgctxt "@tooltip"
-msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distance entre le dos de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:281
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Hauteur du portique"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:239
-msgctxt "@tooltip"
-msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
-msgstr "La différence de hauteur entre la pointe de la buse et le système de portique (axes X et Y). Permet d'empêcher les collisions entre les impressions précédentes et le portique lors d'une impression « Un à la fois »."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:258
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:295
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Nombre d'extrudeuses"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:314
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "Start G-code"
msgstr "G-Code de démarrage"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:324
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr "Commandes G-Code à exécuter au tout début."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:333
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:366
+msgctxt "@title:label"
msgid "End G-code"
msgstr "G-Code de fin"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:343
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very end."
-msgstr "Commandes G-Code à exécuter tout à la fin."
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:42
+msgctxt "@title:tab"
+msgid "Printer"
+msgstr "Imprimante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:374
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:63
+msgctxt "@title:label"
msgid "Nozzle Settings"
msgstr "Paramètres de la buse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr "Taille de la buse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr "Diamètre du matériau compatible"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:404
-msgctxt "@tooltip"
-msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
-msgstr "Le diamètre nominal de filament pris en charge par l'imprimante. Le diamètre exact sera remplacé par le matériau et / ou le profil."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:428
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Décalage buse X"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:440
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:120
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Décalage buse Y"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:452
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:135
msgctxt "@label"
msgid "Cooling Fan Number"
msgstr "Numéro du ventilateur de refroidissement"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:453
-msgctxt "@label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:473
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "Extrudeuse G-Code de démarrage"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:491
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "Extrudeuse G-Code de fin"
@@ -1622,7 +1481,7 @@ msgid "Install"
msgstr "Installer"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Installé"
@@ -1635,18 +1494,18 @@ msgstr "Impossible de se connecter à la base de données Cura Package. Veuillez
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
msgctxt "@label"
msgid "ratings"
-msgstr ""
+msgstr "évaluations"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:28
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:32
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:30
msgctxt "@title:tab"
msgid "Plugins"
msgstr "Plug-ins"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:69
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:42
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:361
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:77
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Matériaux"
@@ -1654,54 +1513,51 @@ msgstr "Matériaux"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
msgctxt "@label"
msgid "Your rating"
-msgstr ""
+msgstr "Votre évaluation"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:98
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:99
msgctxt "@label"
msgid "Version"
msgstr "Version"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:105
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:106
msgctxt "@label"
msgid "Last updated"
msgstr "Dernière mise à jour"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:112
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:260
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:113
msgctxt "@label"
msgid "Author"
msgstr "Auteur"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:119
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:120
msgctxt "@label"
msgid "Downloads"
msgstr "Téléchargements"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:181
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:222
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:265
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Inconnu"
-
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:56
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to install or update"
-msgstr ""
+msgstr "Connexion nécessaire pour l'installation ou la mise à jour"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:73
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:80
+msgctxt "@label:The string between and is the highlighted link"
+msgid "Buy material spools"
+msgstr "Acheter des bobines de matériau"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:96
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:34
msgctxt "@action:button"
msgid "Update"
msgstr "Mise à jour"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:74
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:97
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:35
msgctxt "@action:button"
msgid "Updating"
msgstr "Mise à jour"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:75
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:98
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:36
msgctxt "@action:button"
msgid "Updated"
@@ -1710,7 +1566,7 @@ msgstr "Mis à jour"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
msgid "Marketplace"
-msgstr ""
+msgstr "Marché en ligne"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1745,12 +1601,12 @@ msgstr "Confirmer"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to login first before you can rate"
-msgstr ""
+msgstr "Vous devez être connecté avant de pouvoir effectuer une évaluation"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to install the package before you can rate"
-msgstr ""
+msgstr "Vous devez installer le paquet avant de pouvoir effectuer une évaluation"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
@@ -1762,22 +1618,22 @@ msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Quitter Cura"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Contributions"
msgstr "Contributions de la communauté"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Plugins"
msgstr "Plug-ins de la communauté"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:43
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:40
msgctxt "@label"
msgid "Generic Materials"
msgstr "Matériaux génériques"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:56
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Installé"
@@ -1790,7 +1646,7 @@ msgstr "S'installera au redémarrage"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:53
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to update"
-msgstr ""
+msgstr "Connexion nécessaire pour effectuer la mise à jour"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
@@ -1833,42 +1689,62 @@ msgctxt "@label"
msgid "Featured"
msgstr "Fonctionnalités"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:34
msgctxt "@label"
msgid "Compatibility"
msgstr "Compatibilité"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:124
+msgctxt "@label:table_header"
+msgid "Machine"
+msgstr "Machine"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:137
+msgctxt "@label:table_header"
+msgid "Build Plate"
+msgstr "Plateau"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:143
+msgctxt "@label:table_header"
+msgid "Support"
+msgstr "Support"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:149
+msgctxt "@label:table_header"
+msgid "Quality"
+msgstr "Qualité"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:170
msgctxt "@action:label"
msgid "Technical Data Sheet"
-msgstr ""
+msgstr "Fiche technique"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:179
msgctxt "@action:label"
msgid "Safety Data Sheet"
-msgstr ""
+msgstr "Fiche de sécurité"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:188
msgctxt "@action:label"
msgid "Printing Guidelines"
-msgstr ""
+msgstr "Directives d'impression"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:197
msgctxt "@action:label"
msgid "Website"
-msgstr ""
+msgstr "Site Internet"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml:16
msgctxt "@info"
msgid "Fetching packages..."
msgstr "Récupération des paquets..."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:90
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:91
msgctxt "@label"
msgid "Website"
msgstr "Site Internet"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:97
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "E-mail"
@@ -1878,22 +1754,6 @@ msgctxt "@info:tooltip"
msgid "Some things could be problematic in this print. Click to see tips for adjustment."
msgstr "Certains éléments pourraient causer des problèmes à cette impression. Cliquez pour voir les conseils d'ajustement."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
-msgctxt "@label"
-msgid "Changelog"
-msgstr "Récapitulatif des changements"
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:85
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
-msgctxt "@action:button"
-msgid "Close"
-msgstr "Fermer"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
msgctxt "@title"
msgid "Update Firmware"
@@ -1969,77 +1829,79 @@ msgctxt "@label"
msgid "Firmware update failed due to missing firmware."
msgstr "Échec de la mise à jour du firmware en raison du firmware manquant."
-#: /home/ruben/Projects/Cura/plugins/UserAgreement/UserAgreement.qml:16
-msgctxt "@title:window"
-msgid "User Agreement"
-msgstr "Accord utilisateur"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:155
+msgctxt "@label link to Connect and Cloud interfaces"
+msgid "Manage printer"
+msgstr "Gérer l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:254
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:192
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:183
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
+msgstr "Verre"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:256
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:514
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:248
msgctxt "@info"
-msgid "These options are not available because you are monitoring a cloud printer."
-msgstr ""
+msgid "Please update your printer's firmware to manage the queue remotely."
+msgstr "Veuillez mettre à jour le Firmware de votre imprimante pour gérer la file d'attente à distance."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:289
msgctxt "@info"
msgid "The webcam is not available because you are monitoring a cloud printer."
-msgstr ""
+msgstr "La webcam n'est pas disponible car vous surveillez une imprimante cloud."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:301
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:348
msgctxt "@label:status"
msgid "Loading..."
-msgstr ""
+msgstr "Chargement..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:305
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:352
msgctxt "@label:status"
msgid "Unavailable"
msgstr "Indisponible"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:309
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:356
msgctxt "@label:status"
msgid "Unreachable"
-msgstr ""
+msgstr "Injoignable"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:360
msgctxt "@label:status"
msgid "Idle"
-msgstr ""
+msgstr "Inactif"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
msgctxt "@label"
msgid "Untitled"
-msgstr ""
+msgstr "Sans titre"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:373
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:422
msgctxt "@label"
msgid "Anonymous"
-msgstr ""
+msgstr "Anonyme"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:399
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:449
msgctxt "@label:status"
msgid "Requires configuration changes"
-msgstr ""
+msgstr "Nécessite des modifications de configuration"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:436
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:487
msgctxt "@action:button"
msgid "Details"
-msgstr ""
+msgstr "Détails"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
msgctxt "@label"
msgid "Unavailable printer"
-msgstr ""
+msgstr "Imprimante indisponible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:134
msgctxt "@label"
msgid "First available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:187
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:132
-msgctxt "@label"
-msgid "Glass"
-msgstr "Verre"
+msgstr "Premier disponible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
msgctxt "@label"
@@ -2048,196 +1910,193 @@ msgstr "Mis en file d'attente"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
msgctxt "@label link to connect manager"
-msgid "Go to Cura Connect"
-msgstr ""
+msgid "Manage in browser"
+msgstr "Gérer dans le navigateur"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:100
+msgctxt "@label"
+msgid "There are no print jobs in the queue. Slice and send a job to add one."
+msgstr "Il n'y a pas de travaux d'impression dans la file d'attente. Découpez et envoyez une tache pour en ajouter une."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:115
msgctxt "@label"
msgid "Print jobs"
-msgstr ""
+msgstr "Tâches d'impression"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:131
msgctxt "@label"
msgid "Total print time"
-msgstr ""
+msgstr "Temps total d'impression"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:130
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:147
msgctxt "@label"
msgid "Waiting for"
-msgstr ""
+msgstr "Attente de"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:246
-msgctxt "@label link to connect manager"
-msgid "View print history"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:46
-msgctxt "@window:title"
-msgid "Existing Connection"
-msgstr "Connexion existante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:48
-msgctxt "@message:text"
-msgid "This printer/group is already added to Cura. Please select another printer/group."
-msgstr "Ce groupe / cette imprimante a déjà été ajouté à Cura. Veuillez sélectionner un autre groupe / imprimante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:65
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Connecter à l'imprimante en réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
msgctxt "@label"
-msgid ""
-"To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
-"\n"
-"Select your printer from the list below:"
-msgstr ""
-"Pour imprimer directement sur votre imprimante sur le réseau, assurez-vous que votre imprimante est connectée au réseau via un câble réseau ou en connectant votre imprimante à votre réseau Wi-Fi. Si vous ne connectez pas Cura avec votre imprimante, vous pouvez utiliser une clé USB pour transférer les fichiers g-code sur votre imprimante.\n"
-"\n"
-"Sélectionnez votre imprimante dans la liste ci-dessous :"
+msgid "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer."
+msgstr "Pour imprimer directement sur votre imprimante via le réseau, assurez-vous que votre imprimante est connectée au réseau via un câble Ethernet ou en connectant votre imprimante à votre réseau Wi-Fi. Si vous ne connectez pas Cura avec votre imprimante, vous pouvez utiliser une clé USB pour transférer les fichiers g-code sur votre imprimante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Ajouter"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
+msgctxt "@label"
+msgid "Select your printer from the list below:"
+msgstr "Sélectionnez votre imprimante dans la liste ci-dessous :"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:97
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
msgctxt "@action:button"
msgid "Edit"
msgstr "Modifier"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:108
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:138
msgctxt "@action:button"
msgid "Remove"
msgstr "Supprimer"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:96
msgctxt "@action:button"
msgid "Refresh"
msgstr "Rafraîchir"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:211
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:176
msgctxt "@label"
msgid "If your printer is not listed, read the network printing troubleshooting guide"
msgstr "Si votre imprimante n'apparaît pas dans la liste, lisez le guide de dépannage de l'impression en réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:240
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:258
msgctxt "@label"
msgid "Type"
msgstr "Type"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:279
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:274
msgctxt "@label"
msgid "Firmware version"
msgstr "Version du firmware"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:290
msgctxt "@label"
msgid "Address"
msgstr "Adresse"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:317
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:263
msgctxt "@label"
msgid "This printer is not set up to host a group of printers."
msgstr "Cette imprimante n'est pas configurée pour héberger un groupe d'imprimantes."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:267
msgctxt "@label"
msgid "This printer is the host for a group of %1 printers."
msgstr "Cette imprimante est l'hôte d'un groupe d'imprimantes %1."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:332
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:278
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr "L'imprimante à cette adresse n'a pas encore répondu."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:337
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
msgctxt "@action:button"
msgid "Connect"
msgstr "Connecter"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:351
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:296
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Adresse IP non valide"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:146
+msgctxt "@text"
+msgid "Please enter a valid IP address."
+msgstr "Veuillez saisir une adresse IP valide."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:308
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Adresse de l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:374
-msgctxt "@alabel"
-msgid "Enter the IP address or hostname of your printer on the network."
-msgstr "Saisissez l'adresse IP ou le nom d'hôte de votre imprimante sur le réseau."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
+msgid "Enter the IP address of your printer on the network."
+msgstr "Saisissez l'adresse IP de votre imprimante sur le réseau."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:404
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:361
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:138
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
msgstr "OK"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
msgctxt "@label:status"
msgid "Aborted"
msgstr "Abandonné"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:80
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:82
msgctxt "@label:status"
msgid "Finished"
msgstr "Terminé"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:86
msgctxt "@label:status"
msgid "Preparing..."
-msgstr ""
+msgstr "Préparation..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
msgctxt "@label:status"
msgid "Aborting..."
-msgstr ""
+msgstr "Abandon..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
msgctxt "@label:status"
msgid "Pausing..."
-msgstr ""
+msgstr "Mise en pause..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:104
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
msgctxt "@label:status"
msgid "Paused"
msgstr "En pause"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
msgctxt "@label:status"
msgid "Resuming..."
-msgstr ""
+msgstr "Reprise..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:108
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
msgctxt "@label:status"
msgid "Action required"
msgstr "Action requise"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:110
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
msgctxt "@label:status"
msgid "Finishes %1 at %2"
-msgstr ""
+msgstr "Finit %1 à %2"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:44
-msgctxt "@action:button"
-msgid "Print"
-msgstr "Imprimer"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:11
msgctxt "@title:window"
msgid "Print over network"
msgstr "Imprimer sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:52
+msgctxt "@action:button"
+msgid "Print"
+msgstr "Imprimer"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:80
msgctxt "@label"
msgid "Printer selection"
msgstr "Sélection d'imprimantes"
@@ -2261,12 +2120,12 @@ msgstr "Reprendre"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
msgctxt "@label"
msgid "Pausing..."
-msgstr ""
+msgstr "Mise en pause..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
msgctxt "@label"
msgid "Resuming..."
-msgstr ""
+msgstr "Reprise..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
@@ -2278,7 +2137,7 @@ msgstr "Pause"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Aborting..."
-msgstr ""
+msgstr "Abandon..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
@@ -2319,161 +2178,155 @@ msgstr "Abandonner l'impression"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
msgctxt "@title:window"
msgid "Configuration Changes"
-msgstr ""
+msgstr "Modifications de configuration"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
msgctxt "@action:button"
msgid "Override"
-msgstr ""
+msgstr "Remplacer"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:64
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:85
msgctxt "@label"
msgid "The assigned printer, %1, requires the following configuration change:"
msgid_plural "The assigned printer, %1, requires the following configuration changes:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "L'imprimante assignée, %1, nécessite la modification de configuration suivante :"
+msgstr[1] "L'imprimante assignée, %1, nécessite les modifications de configuration suivantes :"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:68
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:89
msgctxt "@label"
msgid "The printer %1 is assigned, but the job contains an unknown material configuration."
msgstr "L'imprimante %1 est assignée, mais le projet contient une configuration matérielle inconnue."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:99
msgctxt "@label"
msgid "Change material %1 from %2 to %3."
msgstr "Changer le matériau %1 de %2 à %3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:102
msgctxt "@label"
msgid "Load %3 as material %1 (This cannot be overridden)."
msgstr "Charger %3 comme matériau %1 (Ceci ne peut pas être remplacé)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:105
msgctxt "@label"
msgid "Change print core %1 from %2 to %3."
msgstr "Changer le print core %1 de %2 à %3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:108
msgctxt "@label"
msgid "Change build plate to %1 (This cannot be overridden)."
msgstr "Changer le plateau en %1 (Ceci ne peut pas être remplacé)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:94
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:115
msgctxt "@label"
msgid "Override will use the specified settings with the existing printer configuration. This may result in a failed print."
-msgstr ""
+msgstr "Si vous sélectionnez « Remplacer », les paramètres de la configuration actuelle de l'imprimante seront utilisés. Cela peut entraîner l'échec de l'impression."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:135
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:156
msgctxt "@label"
msgid "Aluminum"
msgstr "Aluminium"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:75
-msgctxt "@info:tooltip"
-msgid "Connect to a printer"
-msgstr "Connecter à une imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:92
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:100
msgctxt "@info"
msgid ""
"Please make sure your printer has a connection:\n"
"- Check if the printer is turned on.\n"
-"- Check if the printer is connected to the network."
+"- Check if the printer is connected to the network.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
+"Assurez-vous que votre imprimante est connectée :\n"
+"- Vérifiez si l'imprimante est sous tension.\n"
+"- Vérifiez si l'imprimante est connectée au réseau.- Vérifiez si vous êtes connecté pour découvrir les imprimantes connectées au cloud."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:110
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
msgctxt "@info"
-msgid "Please select a network connected printer to monitor."
-msgstr ""
+msgid "Please connect your printer to the network."
+msgstr "Veuillez connecter votre imprimante au réseau."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:126
-msgctxt "@info"
-msgid "Please connect your Ultimaker printer to your local network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:165
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
msgctxt "@label link to technical assistance"
msgid "View user manuals online"
-msgstr ""
+msgstr "Voir les manuels d'utilisation en ligne"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:18
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:47
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr "Modèle de couleurs"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:105
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Couleur du matériau"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:109
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Type de ligne"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:113
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Taux d'alimentation"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:117
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Épaisseur de la couche"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:154
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Mode de compatibilité"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:229
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
msgid "Travels"
-msgstr ""
+msgstr "Déplacements"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:235
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
msgid "Helpers"
-msgstr ""
+msgstr "Aides"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:241
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
msgid "Shell"
-msgstr ""
+msgstr "Coque"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:247
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
msgid "Infill"
msgstr "Remplissage"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Afficher uniquement les couches supérieures"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:307
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:308
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr "Afficher 5 niveaux détaillés en haut"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Haut / bas"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:325
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Paroi interne"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:432
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -2503,30 +2356,25 @@ msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Modifier les scripts de post-traitement actifs"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:16
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:17
msgctxt "@title:window"
msgid "More information on anonymous data collection"
msgstr "Plus d'informations sur la collecte de données anonymes"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:66
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:74
msgctxt "@text:window"
-msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
-msgstr "Cura envoie des données anonymes à Ultimaker afin d'améliorer la qualité d'impression et l'expérience utilisateur. Voici un exemple de toutes les données envoyées."
+msgid "Ultimaker Cura collects anonymous data in order to improve the print quality and user experience. Below is an example of all the data that is shared:"
+msgstr "Ultimaker Cura recueille des données anonymes afin d'améliorer la qualité d'impression et l'expérience utilisateur. Voici un exemple de toutes les données partagées :"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:101
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:109
msgctxt "@text:window"
-msgid "I don't want to send this data"
-msgstr ""
+msgid "I don't want to send anonymous data"
+msgstr "Je ne veux pas envoyer de données anonymes"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:111
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:118
msgctxt "@text:window"
-msgid "Allow sending this data to Ultimaker and help us improve Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/R2D2/EvaluationSidebar.qml:49
-msgctxt "@label"
-msgid "No print selected"
-msgstr ""
+msgid "Allow sending anonymous data"
+msgstr "Autoriser l'envoi de données anonymes"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
msgctxt "@title:window"
@@ -2575,19 +2423,19 @@ msgstr "Profondeur (mm)"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:126
msgctxt "@info:tooltip"
-msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
-msgstr "Par défaut, les pixels blancs représentent les points hauts sur la maille tandis que les pixels noirs représentent les points bas sur la maille. Modifiez cette option pour inverser le comportement de manière à ce que les pixels noirs représentent les points hauts sur la maille et les pixels blancs les points bas."
-
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
-msgctxt "@item:inlistbox"
-msgid "Lighter is higher"
-msgstr "Le plus clair est plus haut"
+msgid "For lithophanes dark pixels should correspond to thicker locations in order to block more light coming through. For height maps lighter pixels signify higher terrain, so lighter pixels should correspond to thicker locations in the generated 3D model."
+msgstr "Pour les lithophanies, les pixels foncés doivent correspondre à des emplacements plus épais afin d'empêcher la lumière de passer. Pour des cartes de hauteur, les pixels clairs signifient un terrain plus élevé, de sorte que les pixels clairs doivent correspondre à des emplacements plus épais dans le modèle 3D généré."
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
msgctxt "@item:inlistbox"
msgid "Darker is higher"
msgstr "Le plus foncé est plus haut"
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
+msgctxt "@item:inlistbox"
+msgid "Lighter is higher"
+msgstr "Le plus clair est plus haut"
+
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:149
msgctxt "@info:tooltip"
msgid "The amount of smoothing to apply to the image."
@@ -2598,70 +2446,69 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Lissage"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:37
-msgctxt "@label"
-msgid "Mesh Type"
-msgstr "Type de maille"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:68
-msgctxt "@label"
-msgid "Normal model"
-msgstr "Modèle normal"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:75
-msgctxt "@label"
-msgid "Print as support"
-msgstr "Imprimer comme support"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:83
-msgctxt "@label"
-msgid "Don't support overlap with other models"
-msgstr "Ne pas prendre en charge le chevauchement avec d'autres modèles"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:91
-msgctxt "@label"
-msgid "Modify settings for overlap with other models"
-msgstr "Modifier les paramètres de chevauchement avec d'autres modèles"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:99
-msgctxt "@label"
-msgid "Modify settings for infill of other models"
-msgstr "Modifier les paramètres de remplissage d'autres modèles"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
-msgctxt "@action:button"
-msgid "Select settings"
-msgstr "Sélectionner les paramètres"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:13
msgctxt "@title:window"
msgid "Select Settings to Customize for this model"
msgstr "Sélectionner les paramètres pour personnaliser ce modèle"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:431
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:56
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtrer..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:445
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:70
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Afficher tout"
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:44
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Type de maille"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:85
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Modèle normal"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:97
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Imprimer comme support"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:109
+msgctxt "@label"
+msgid "Modify settings for overlaps"
+msgstr "Modifier les paramètres de chevauchement"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:121
+msgctxt "@label"
+msgid "Don't support overlaps"
+msgstr "Ne prend pas en charge le chevauchement"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:145
+msgctxt "@action:checkbox"
+msgid "Infill only"
+msgstr "Remplissage uniquement"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:368
+msgctxt "@action:button"
+msgid "Select settings"
+msgstr "Sélectionner les paramètres"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:14
msgctxt "@title:window"
msgid "Open Project"
msgstr "Ouvrir un projet"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:58
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Update/override existing profile"
msgid "Update existing"
msgstr "Mettre à jour l'existant"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:59
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Save settings in a new profile"
msgid "Create new"
msgstr "Créer"
@@ -2688,6 +2535,11 @@ msgctxt "@action:ComboBox option"
msgid "Update"
msgstr "Mise à jour"
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
+msgctxt "@action:ComboBox option"
+msgid "Create new"
+msgstr "Créer"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
@@ -2701,7 +2553,7 @@ msgid "Printer Group"
msgstr "Groupe d'imprimantes"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:220
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Paramètres de profil"
@@ -2712,75 +2564,81 @@ msgid "How should the conflict in the profile be resolved?"
msgstr "Comment le conflit du profil doit-il être résolu ?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:323
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:221
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:244
msgctxt "@action:label"
msgid "Name"
msgstr "Nom"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:261
+msgctxt "@action:label"
+msgid "Intent"
+msgstr "Intent"
+
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:228
msgctxt "@action:label"
msgid "Not in profile"
msgstr "Absent du profil"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:210
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:233
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
msgstr[0] "%1 écrasent"
msgstr[1] "%1 écrase"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:247
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:262
msgctxt "@action:label"
msgid "Derivative from"
msgstr "Dérivé de"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:252
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:267
msgctxt "@action:label"
msgid "%1, %2 override"
msgid_plural "%1, %2 overrides"
msgstr[0] "%1, %2 écrasent"
msgstr[1] "%1, %2 écrase"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:268
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:283
msgctxt "@action:label"
msgid "Material settings"
msgstr "Paramètres du matériau"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:284
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:299
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
msgstr "Comment le conflit du matériau doit-il être résolu ?"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:342
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Visibilité des paramètres"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:336
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:351
msgctxt "@action:label"
msgid "Mode"
msgstr "Mode"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:367
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Paramètres visibles :"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:372
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 sur %2"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:383
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:398
msgctxt "@action:warning"
msgid "Loading a project will clear all models on the build plate."
msgstr "Le chargement d'un projet effacera tous les modèles sur le plateau."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:401
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:416
msgctxt "@action:button"
msgid "Open"
msgstr "Ouvrir"
@@ -2788,285 +2646,140 @@ msgstr "Ouvrir"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
msgctxt "@title"
msgid "My Backups"
-msgstr ""
+msgstr "Mes sauvegardes"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:38
msgctxt "@empty_state"
msgid "You don't have any backups currently. Use the 'Backup Now' button to create one."
-msgstr ""
+msgstr "Vous n'avez actuellement aucune sauvegarde. Utilisez le bouton « Sauvegarder maintenant » pour en créer une."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:60
msgctxt "@backup_limit_info"
msgid "During the preview phase, you'll be limited to 5 visible backups. Remove a backup to see older ones."
-msgstr ""
+msgstr "Pendant la phase de prévisualisation, vous ne pourrez voir qu'un maximum de 5 sauvegardes. Supprimez une sauvegarde pour voir les plus anciennes."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:34
msgctxt "@description"
msgid "Backup and synchronize your Cura settings."
-msgstr ""
+msgstr "Sauvegardez et synchronisez vos paramètres Cura."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:51
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:138
msgctxt "@button"
msgid "Sign in"
-msgstr ""
+msgstr "Se connecter"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
msgctxt "@title:window"
msgid "Cura Backups"
-msgstr ""
+msgstr "Sauvegardes Cura"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
msgctxt "@backuplist:label"
msgid "Cura Version"
-msgstr ""
+msgstr "Version Cura"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
msgctxt "@backuplist:label"
msgid "Machines"
-msgstr ""
+msgstr "Machines"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
msgctxt "@backuplist:label"
msgid "Materials"
-msgstr ""
+msgstr "Matériaux"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
msgctxt "@backuplist:label"
msgid "Profiles"
-msgstr ""
+msgstr "Profils"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
msgctxt "@backuplist:label"
msgid "Plugins"
-msgstr ""
+msgstr "Plug-ins"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
msgctxt "@button"
msgid "Restore"
-msgstr ""
+msgstr "Restaurer"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
msgctxt "@dialog:title"
msgid "Delete Backup"
-msgstr ""
+msgstr "Supprimer la sauvegarde"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:100
msgctxt "@dialog:info"
msgid "Are you sure you want to delete this backup? This cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette sauvegarde ? Il est impossible d'annuler cette action."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:108
msgctxt "@dialog:title"
msgid "Restore Backup"
-msgstr ""
+msgstr "Restaurer la sauvegarde"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:109
msgctxt "@dialog:info"
msgid "You will need to restart Cura before your backup is restored. Do you want to close Cura now?"
-msgstr ""
+msgstr "Vous devez redémarrer Cura avant que votre sauvegarde ne soit restaurée. Voulez-vous fermer Cura maintenant ?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:22
msgctxt "@button"
msgid "Want more?"
-msgstr ""
+msgstr "Vous en voulez plus ?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
msgctxt "@button"
msgid "Backup Now"
-msgstr ""
+msgstr "Sauvegarder maintenant"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
msgctxt "@checkbox:description"
msgid "Auto Backup"
-msgstr ""
+msgstr "Sauvegarde automatique"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:44
msgctxt "@checkbox:description"
msgid "Automatically create a backup each day that Cura is started."
-msgstr ""
+msgstr "Créez automatiquement une sauvegarde chaque jour où Cura est démarré."
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMainSettingsSelector.qml:75
-msgctxt "@label"
-msgid "Not supported"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:35
-msgctxt "@action:button"
-msgid "Previous"
-msgstr "Précédent"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
-msgctxt "@action:button"
-msgid "Export"
-msgstr "Exporter"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Suivant"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:169
-msgctxt "@label"
-msgid "Tip"
-msgstr "Astuce"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:160
-msgctxt "@label"
-msgid "Print experiment"
-msgstr "Test d'impression"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageValidation.qml:25
-msgctxt "@label"
-msgid "Checklist"
-msgstr "Liste de contrôle"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:26
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:25
-msgctxt "@title"
-msgid "Select Printer Upgrades"
-msgstr "Sélectionner les mises à niveau de l'imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:38
-msgctxt "@label"
-msgid "Please select any upgrades made to this Ultimaker 2."
-msgstr "Sélectionnez les mises à niveau disponibles pour cet Ultimaker 2."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
-msgctxt "@label"
-msgid "Olsson Block"
-msgstr "Blocage Olsson"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:30
msgctxt "@title"
msgid "Build Plate Leveling"
msgstr "Nivellement du plateau"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:38
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:44
msgctxt "@label"
msgid "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted."
msgstr "Pour obtenir des résultats d'impression optimaux, vous pouvez maintenant régler votre plateau. Quand vous cliquez sur 'Aller à la position suivante', la buse se déplacera vers les différentes positions pouvant être réglées."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:57
msgctxt "@label"
msgid "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle."
msgstr "Pour chacune des positions ; glissez un bout de papier sous la buse et ajustez la hauteur du plateau. La hauteur du plateau est juste lorsque la pointe de la buse gratte légèrement le papier."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:62
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:75
msgctxt "@action:button"
msgid "Start Build Plate Leveling"
msgstr "Démarrer le nivellement du plateau"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:74
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:87
msgctxt "@action:button"
msgid "Move to Next Position"
msgstr "Aller à la position suivante"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:37
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker Original"
msgstr "Sélectionnez les mises à niveau disponibles pour cet Ultimaker Original"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:45
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:41
msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Plateau chauffant (kit officiel ou fabriqué soi-même)"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
-msgctxt "@title"
-msgid "Check Printer"
-msgstr "Tester l'imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
-msgctxt "@label"
-msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
-msgstr "Il est préférable de procéder à quelques tests de fonctionnement sur votre Ultimaker. Vous pouvez passer cette étape si vous savez que votre machine est fonctionnelle"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
-msgctxt "@action:button"
-msgid "Start Printer Check"
-msgstr "Démarrer le test de l'imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
-msgctxt "@label"
-msgid "Connection: "
-msgstr "Connexion : "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Connected"
-msgstr "Connecté"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Not connected"
-msgstr "Non connecté"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
-msgctxt "@label"
-msgid "Min endstop X: "
-msgstr "Fin de course X : "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-msgctxt "@info:status"
-msgid "Works"
-msgstr "Fonctionne"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Not checked"
-msgstr "Non testé"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
-msgctxt "@label"
-msgid "Min endstop Y: "
-msgstr "Fin de course Y : "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
-msgctxt "@label"
-msgid "Min endstop Z: "
-msgstr "Fin de course Z : "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
-msgctxt "@label"
-msgid "Nozzle temperature check: "
-msgstr "Test de la température de la buse : "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Stop Heating"
-msgstr "Arrêter le chauffage"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Start Heating"
-msgstr "Démarrer le chauffage"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
-msgctxt "@label"
-msgid "Build plate temperature check:"
-msgstr "Contrôle de la température du plateau :"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Checked"
-msgstr "Contrôlée"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
-msgctxt "@label"
-msgid "Everything is in order! You're done with your CheckUp."
-msgstr "Tout est en ordre ! Vous avez terminé votre check-up."
-
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
@@ -3117,170 +2830,176 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Êtes-vous sûr(e) de vouloir abandonner l'impression ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
msgctxt "@title"
msgid "Information"
msgstr "Informations"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
msgctxt "@title:window"
msgid "Confirm Diameter Change"
msgstr "Confirmer le changement de diamètre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:102
msgctxt "@label (%1 is a number)"
msgid "The new filament diameter is set to %1 mm, which is not compatible with the current extruder. Do you wish to continue?"
msgstr "Le nouveau diamètre de filament est réglé sur %1 mm, ce qui n'est pas compatible avec l'extrudeuse actuelle. Souhaitez-vous poursuivre ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:128
msgctxt "@label"
msgid "Display Name"
msgstr "Afficher le nom"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:138
msgctxt "@label"
msgid "Brand"
msgstr "Marque"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:148
msgctxt "@label"
msgid "Material Type"
msgstr "Type de matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:158
msgctxt "@label"
msgid "Color"
msgstr "Couleur"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:208
msgctxt "@label"
msgid "Properties"
msgstr "Propriétés"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:214
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:210
msgctxt "@label"
msgid "Density"
msgstr "Densité"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:229
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:225
msgctxt "@label"
msgid "Diameter"
msgstr "Diamètre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:259
msgctxt "@label"
msgid "Filament Cost"
msgstr "Coût du filament"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:276
msgctxt "@label"
msgid "Filament weight"
msgstr "Poids du filament"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:294
msgctxt "@label"
msgid "Filament length"
msgstr "Longueur du filament"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:307
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:303
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Coût au mètre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:317
msgctxt "@label"
msgid "This material is linked to %1 and shares some of its properties."
msgstr "Ce matériau est lié à %1 et partage certaines de ses propriétés."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:324
msgctxt "@label"
msgid "Unlink Material"
msgstr "Délier le matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:339
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:335
msgctxt "@label"
msgid "Description"
msgstr "Description"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:352
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:348
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Informations d'adhérence"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:17
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
msgctxt "@label"
msgid "Print settings"
msgstr "Paramètres d'impression"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:84
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:84
msgctxt "@action:button"
msgid "Activate"
msgstr "Activer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:126
msgctxt "@action:button"
msgid "Create"
msgstr "Créer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:140
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Dupliquer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:141
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:167
msgctxt "@action:button"
msgid "Import"
msgstr "Importer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:203
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:179
+msgctxt "@action:button"
+msgid "Export"
+msgstr "Exporter"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:233
msgctxt "@action:label"
msgid "Printer"
msgstr "Imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:262
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:274
msgctxt "@title:window"
msgid "Confirm Remove"
msgstr "Confirmer la suppression"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:263
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:247
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:300
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:275
msgctxt "@label (%1 is object name)"
msgid "Are you sure you wish to remove %1? This cannot be undone!"
msgstr "Êtes-vous sûr de vouloir supprimer l'objet %1 ? Vous ne pourrez pas revenir en arrière !"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:277
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:285
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:322
msgctxt "@title:window"
msgid "Import Material"
msgstr "Importer un matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:323
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Could not import material %1: %2"
msgstr "Impossible d'importer le matériau %1 : %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:327
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully imported material %1"
msgstr "Matériau %1 importé avec succès"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:316
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:345
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:353
msgctxt "@title:window"
msgid "Export Material"
msgstr "Exporter un matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:357
msgctxt "@info:status Don't translate the XML tags and !"
msgid "Failed to export material to %1: %2"
msgstr "Échec de l'exportation de matériau vers %1 : %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:363
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Matériau exporté avec succès vers %1"
@@ -3295,415 +3014,425 @@ msgctxt "@label:textbox"
msgid "Check all"
msgstr "Vérifier tout"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:47
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:61
msgctxt "@info:status"
msgid "Calculated"
msgstr "Calculer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:75
msgctxt "@title:column"
msgid "Setting"
msgstr "Paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
msgctxt "@title:column"
msgid "Profile"
msgstr "Profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:74
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:89
msgctxt "@title:column"
msgid "Current"
msgstr "Actuel"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:97
msgctxt "@title:column"
msgid "Unit"
msgstr "Unité"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr "Général"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:126
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:132
msgctxt "@label"
msgid "Interface"
msgstr "Interface"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:143
msgctxt "@label"
msgid "Language:"
msgstr "Langue :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:210
msgctxt "@label"
msgid "Currency:"
msgstr "Devise :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:223
msgctxt "@label"
msgid "Theme:"
msgstr "Thème :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:273
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:279
msgctxt "@label"
msgid "You will need to restart the application for these changes to have effect."
msgstr "Vous devez redémarrer l'application pour que ces changements prennent effet."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:296
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Découper automatiquement si les paramètres sont modifiés."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Découper automatiquement"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:312
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportement Viewport"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
msgctxt "@info:tooltip"
msgid "Highlight unsupported areas of the model in red. Without support these areas will not print properly."
msgstr "Surligne les parties non supportées du modèle en rouge. Sans ajouter de support, ces zones ne s'imprimeront pas correctement."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:335
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Mettre en surbrillance les porte-à-faux"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:343
msgctxt "@info:tooltip"
msgid "Moves the camera so the model is in the center of the view when a model is selected"
msgstr "Déplace la caméra afin que le modèle sélectionné se trouve au centre de la vue"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:348
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr "Centrer la caméra lorsqu'un élément est sélectionné"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Le comportement de zoom par défaut de Cura doit-il être inversé ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:355
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Inverser la direction du zoom de la caméra."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr "Le zoom doit-il se faire dans la direction de la souris ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
+msgctxt "@info:tooltip"
+msgid "Zooming towards the mouse is not supported in the orthographic perspective."
+msgstr "Le zoom vers la souris n'est pas pris en charge dans la perspective orthographique."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoomer vers la direction de la souris"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:380
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:410
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved so that they no longer intersect?"
msgstr "Les modèles dans la zone d'impression doivent-ils être déplacés afin de ne plus se croiser ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:385
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr "Veillez à ce que les modèles restent séparés"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:394
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:424
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved down to touch the build plate?"
msgstr "Les modèles dans la zone d'impression doivent-ils être abaissés afin de toucher le plateau ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:429
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr "Abaisser automatiquement les modèles sur le plateau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:411
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr "Afficher le message d'avertissement dans le lecteur G-Code."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr "Message d'avertissement dans le lecteur G-Code"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:428
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:458
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "La couche doit-elle être forcée en mode de compatibilité ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:463
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr "Forcer l'affichage de la couche en mode de compatibilité (redémarrage requis)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
+msgctxt "@info:tooltip"
+msgid "Should Cura open at the location it was closed?"
+msgstr "Est-ce que Cura devrait ouvrir à l'endroit où il a été fermé ?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
+msgctxt "@option:check"
+msgid "Restore window position on start"
+msgstr "Restaurer la position de la fenêtre au démarrage"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:488
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr "Quel type de rendu de la caméra doit-il être utilisé?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:495
+msgctxt "@window:text"
+msgid "Camera rendering:"
+msgstr "Rendu caméra :"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+msgid "Perspective"
+msgstr "Perspective"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+msgid "Orthographic"
+msgstr "Orthographique"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Ouvrir et enregistrer des fichiers"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:456
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:545
msgctxt "@info:tooltip"
msgid "Should models be scaled to the build volume if they are too large?"
msgstr "Les modèles doivent-ils être mis à l'échelle du volume d'impression s'ils sont trop grands ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:461
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:550
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Réduire la taille des modèles trop grands"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:560
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Un modèle peut apparaître en tout petit si son unité est par exemple en mètres plutôt qu'en millimètres. Ces modèles doivent-ils être agrandis ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:565
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Mettre à l'échelle les modèles extrêmement petits"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr "Les modèles doivent-ils être sélectionnés après leur chargement ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:491
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:580
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr "Sélectionner les modèles lorsqu'ils sont chargés"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
msgctxt "@info:tooltip"
msgid "Should a prefix based on the printer name be added to the print job name automatically?"
msgstr "Un préfixe basé sur le nom de l'imprimante doit-il être automatiquement ajouté au nom de la tâche d'impression ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr "Ajouter le préfixe de la machine au nom de la tâche"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:516
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:605
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr "Un résumé doit-il être affiché lors de l'enregistrement d'un fichier de projet ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:609
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr "Afficher la boîte de dialogue du résumé lors de l'enregistrement du projet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Comportement par défaut lors de l'ouverture d'un fichier de projet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:627
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Comportement par défaut lors de l'ouverture d'un fichier de projet : "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Toujours me demander"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:642
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Toujours ouvrir comme projet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:554
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Toujours importer les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:679
msgctxt "@info:tooltip"
msgid "When you have made changes to a profile and switched to a different one, a dialog will be shown asking whether you want to keep your modifications or not, or you can choose a default behaviour and never show that dialog again."
msgstr "Lorsque vous apportez des modifications à un profil puis passez à un autre profil, une boîte de dialogue apparaît, vous demandant si vous souhaitez conserver les modifications. Vous pouvez aussi choisir une option par défaut, et le dialogue ne s'affichera plus."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:599
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:52
msgctxt "@label"
msgid "Profiles"
msgstr "Profils"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:693
msgctxt "@window:text"
msgid "Default behavior for changed setting values when switching to a different profile: "
msgstr "Comportement par défaut pour les valeurs de paramètres modifiées lors du passage à un profil différent : "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:707
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:157
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Toujours me demander"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Toujours rejeter les paramètres modifiés"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:709
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr "Toujours transférer les paramètres modifiés dans le nouveau profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:654
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
msgctxt "@label"
msgid "Privacy"
msgstr "Confidentialité"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:661
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:750
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr "Cura doit-il vérifier les mises à jour au démarrage du programme ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:666
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:755
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Vérifier les mises à jour au démarrage"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:676
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:765
msgctxt "@info:tooltip"
msgid "Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored."
msgstr "Les données anonymes de votre impression doivent-elles être envoyées à Ultimaker ? Notez qu'aucun modèle, aucune adresse IP ni aucune autre information permettant de vous identifier personnellement ne seront envoyés ou stockés."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:681
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:770
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Envoyer des informations (anonymes) sur l'impression"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:690
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:779
msgctxt "@action:button"
msgid "More information"
msgstr "Plus d'informations"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
-msgctxt "@label"
-msgid "Experimental"
-msgstr "Expérimental"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:715
-msgctxt "@info:tooltip"
-msgid "Use multi build plate functionality"
-msgstr "Utiliser la fonctionnalité multi-plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
-msgctxt "@option:check"
-msgid "Use multi build plate functionality (restart required)"
-msgstr "Utiliser la fonctionnalité multi-plateau (redémarrage requis)"
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:16
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr "Imprimantes"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:57
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:63
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
msgctxt "@action:button"
msgid "Rename"
msgstr "Renommer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:363
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:419
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profils"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:104
msgctxt "@label"
msgid "Create"
msgstr "Créer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@label"
msgid "Duplicate"
msgstr "Dupliquer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:202
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Créer un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:176
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:204
msgctxt "@info"
msgid "Please provide a name for this profile."
-msgstr ""
+msgstr "Veuillez fournir un nom pour ce profil."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:260
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Dupliquer un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:291
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Renommer le profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:276
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:304
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Importer un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:333
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Exporter un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:396
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Imprimante : %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Default profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Custom profiles"
-msgstr "Personnaliser les profils"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:554
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr "Mettre à jour le profil à l'aide des paramètres / forçages actuels"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:561
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:257
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Ignorer les modifications actuelles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:514
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:580
msgctxt "@action:label"
msgid "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below."
msgstr "Ce profil utilise les paramètres par défaut spécifiés par l'imprimante, de sorte qu'aucun paramètre / forçage n'apparaît dans la liste ci-dessous."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:521
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:588
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr "Vos paramètres actuels correspondent au profil sélectionné."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:606
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Paramètres généraux"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:90
msgctxt "@action:button"
msgid "Marketplace"
-msgstr ""
+msgstr "Marché en ligne"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
@@ -3726,7 +3455,7 @@ msgstr "&Visualisation"
#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
msgctxt "@title:menu menubar:toplevel"
msgid "&Settings"
-msgstr ""
+msgstr "&Paramètres"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
msgctxt "@title:menu menubar:toplevel"
@@ -3743,12 +3472,12 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Aide"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
msgctxt "@title:window"
msgid "New project"
msgstr "Nouveau projet"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:125
msgctxt "@info:question"
msgid "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings."
msgstr "Êtes-vous sûr(e) de souhaiter lancer un nouveau projet ? Cela supprimera les objets du plateau ainsi que tous paramètres non enregistrés."
@@ -3760,36 +3489,36 @@ msgstr "Sans titre"
#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "search settings"
-msgstr ""
+msgid "Search settings"
+msgstr "Paramètres de recherche"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:462
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Copier la valeur vers tous les extrudeurs"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:474
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:471
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr "Copier toutes les valeurs modifiées vers toutes les extrudeuses"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Masquer ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:521
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Masquer ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Afficher ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:557
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configurer la visibilité des paramètres..."
@@ -3805,27 +3534,32 @@ msgstr ""
"\n"
"Cliquez pour rendre ces paramètres visibles."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:81
+msgctxt "@label"
+msgid "This setting is not used because all the settings that it influences are overridden."
+msgstr "Ce paramètre n'est pas utilisé car tous les paramètres qu'il influence sont remplacés."
+
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:86
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Touche"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:91
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Touché par"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:166
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:187
msgctxt "@label"
msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders."
msgstr "Ce paramètre est toujours partagé par toutes les extrudeuses. Le modifier ici entraînera la modification de la valeur pour toutes les extrudeuses."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:191
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr "La valeur est résolue à partir des valeurs par extrudeur "
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:230
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3836,7 +3570,7 @@ msgstr ""
"\n"
"Cliquez pour restaurer la valeur du profil."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:329
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3847,87 +3581,79 @@ msgstr ""
"\n"
"Cliquez pour restaurer la valeur calculée."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/NoIntentIcon.qml:31
+msgctxt "@label %1 is filled in with the type of a profile. %2 is filled with a list of numbers (eg '1' or '1, 2')"
+msgid "There is no %1 profile for the configuration in extruder %2. The default intent will be used instead"
+msgid_plural "There is no %1 profile for the configurations in extruders %2. The default intent will be used instead"
+msgstr[0] ""
+msgstr[1] ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
msgctxt "@button"
msgid "Recommended"
-msgstr ""
+msgstr "Recommandé"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
msgctxt "@button"
msgid "Custom"
-msgstr ""
+msgstr "Personnalisé"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
msgctxt "@label"
msgid "Gradual infill"
-msgstr ""
+msgstr "Remplissage graduel"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:232
msgctxt "@label"
msgid "Gradual infill will gradually increase the amount of infill towards the top."
msgstr "Un remplissage graduel augmentera la quantité de remplissage vers le haut."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:29
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:30
msgctxt "@label"
msgid "Support"
-msgstr ""
+msgstr "Support"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:71
msgctxt "@label"
msgid "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."
msgstr "Générer des structures pour soutenir les parties du modèle qui possèdent des porte-à-faux. Sans ces structures, ces parties s'effondreront durant l'impression."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:136
-msgctxt "@label"
-msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
-msgstr "Sélectionnez l'extrudeur à utiliser comme support. Cela créera des structures de support sous le modèle afin de l'empêcher de s'affaisser ou de s'imprimer dans les airs."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:29
msgctxt "@label"
msgid "Adhesion"
-msgstr ""
+msgstr "Adhérence"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:74
msgctxt "@label"
msgid "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."
msgstr "Activez l'impression d'une bordure ou plaquette (Brim/Raft). Cela ajoutera une zone plate autour de ou sous votre objet qui est facile à découper par la suite."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:175
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Hauteur de la couche"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:206
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:81
msgctxt "@tooltip"
msgid "You have modified some profile settings. If you want to change these go to custom mode."
msgstr "Vous avez modifié certains paramètres du profil. Si vous souhaitez les modifier, allez dans le mode Personnaliser."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:355
-msgctxt "@tooltip"
-msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:449
-msgctxt "@tooltip"
-msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
-msgstr "Un profil personnalisé est actuellement actif. Pour activer le curseur de qualité, choisissez un profil de qualité par défaut dans l'onglet Personnaliser"
-
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:13
msgctxt "@label:Should be short"
msgid "On"
-msgstr ""
+msgstr "On"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
msgctxt "@label:Should be short"
msgid "Off"
-msgstr ""
+msgstr "Off"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:33
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Expérimental"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:47
msgctxt "@label"
msgid "Profile"
-msgstr ""
+msgstr "Profil"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:172
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3938,10 +3664,15 @@ msgstr ""
"\n"
"Cliquez pour ouvrir le gestionnaire de profils."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:160
+msgctxt "@label:header"
+msgid "Custom profiles"
+msgstr "Personnaliser les profils"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:21
msgctxt "@label shown when we load a Gcode file"
-msgid "Print setup disabled. G code file can not be modified."
-msgstr ""
+msgid "Print setup disabled. G-code file can not be modified."
+msgstr "Configuration d'impression désactivée. Le fichier G-Code ne peut pas être modifié."
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
@@ -3973,59 +3704,59 @@ msgctxt "@label"
msgid "Send G-code"
msgstr "Envoyer G-Code"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:364
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:365
msgctxt "@tooltip of G-code command input"
msgid "Send a custom G-code command to the connected printer. Press 'enter' to send the command."
msgstr "Envoyer une commande G-Code personnalisée à l'imprimante connectée. Appuyez sur « Entrée » pour envoyer la commande."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:41
msgctxt "@label"
msgid "Extruder"
msgstr "Extrudeuse"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:71
msgctxt "@tooltip"
msgid "The target temperature of the hotend. The hotend will heat up or cool down towards this temperature. If this is 0, the hotend heating is turned off."
msgstr "Température cible de l'extrémité chauffante. L'extrémité chauffante sera chauffée ou refroidie pour tendre vers cette température. Si la valeur est 0, le chauffage de l'extrémité chauffante sera coupé."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:103
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr "Température actuelle de cette extrémité chauffante."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:177
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr "Température jusqu'à laquelle préchauffer l'extrémité chauffante."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:332
msgctxt "@button Cancel pre-heating"
msgid "Cancel"
msgstr "Annuler"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:344
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:335
msgctxt "@button"
msgid "Pre-heat"
msgstr "Préchauffer"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:370
msgctxt "@tooltip of pre-heat"
msgid "Heat the hotend in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the hotend to heat up when you're ready to print."
msgstr "Préchauffez l'extrémité chauffante avant l'impression. Vous pouvez continuer l'ajustement de votre impression pendant qu'elle chauffe, ce qui vous évitera un temps d'attente lorsque vous serez prêt à lancer l'impression."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:406
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr "Couleur du matériau dans cet extrudeur."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:438
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Matériau dans cet extrudeur."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:470
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Buse insérée dans cet extrudeur."
@@ -4065,12 +3796,12 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:46
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Favoris"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:71
msgctxt "@label:category menu label"
msgid "Generic"
msgstr "Générique"
@@ -4090,42 +3821,47 @@ msgctxt "@title:menu menubar:settings"
msgid "&Printer"
msgstr "Im&primante"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:26
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:27
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:36
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Définir comme extrudeur actif"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Enable Extruder"
msgstr "Activer l'extrudeuse"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:49
msgctxt "@action:inmenu"
msgid "Disable Extruder"
msgstr "Désactiver l'extrudeuse"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:62
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "Plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:65
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profil"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:19
msgctxt "@action:inmenu menubar:view"
msgid "&Camera position"
msgstr "Position de la &caméra"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:44
+msgctxt "@action:inmenu menubar:view"
+msgid "Camera view"
+msgstr "Vue de la caméra"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:47
+msgctxt "@action:inmenu menubar:view"
+msgid "Perspective"
+msgstr "Perspective"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:59
+msgctxt "@action:inmenu menubar:view"
+msgid "Orthographic"
+msgstr "Orthographique"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:80
msgctxt "@action:inmenu menubar:view"
msgid "&Build plate"
msgstr "&Plateau"
@@ -4145,17 +3881,17 @@ msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Gérer la visibilité des paramètres..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:33
msgctxt "@title:menu menubar:file"
msgid "&Save..."
msgstr "Enregi&strer..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:54
msgctxt "@title:menu menubar:file"
msgid "&Export..."
msgstr "&Exporter..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:65
msgctxt "@action:inmenu menubar:file"
msgid "Export Selection..."
msgstr "Exporter la sélection..."
@@ -4182,190 +3918,193 @@ msgstr "Nombre de copies"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
msgctxt "@header"
msgid "Configurations"
-msgstr ""
+msgstr "Configurations"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:112
msgctxt "@label"
msgid "Select configuration"
-msgstr ""
+msgstr "Sélectionner la configuration"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:201
-msgctxt "@label"
-msgid "See the material compatibility chart"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:274
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:223
msgctxt "@label"
msgid "Configurations"
-msgstr ""
+msgstr "Configurations"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
msgctxt "@label"
msgid "Loading available configurations from the printer..."
-msgstr ""
+msgstr "Chargement des configurations disponibles à partir de l'imprimante..."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:58
msgctxt "@label"
msgid "The configurations are not available because the printer is disconnected."
-msgstr ""
+msgstr "Les configurations ne sont pas disponibles car l'imprimante est déconnectée."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:25
msgctxt "@header"
msgid "Custom"
-msgstr ""
+msgstr "Personnalisé"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
msgctxt "@label"
msgid "Printer"
-msgstr ""
+msgstr "Imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:202
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
msgctxt "@label"
msgid "Enabled"
-msgstr ""
+msgstr "Activé"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:251
msgctxt "@label"
msgid "Material"
msgstr "Matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:344
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:378
msgctxt "@label"
msgid "Use glue for better adhesion with this material combination."
-msgstr ""
+msgstr "Utiliser de la colle pour une meilleure adhérence avec cette combinaison de matériaux."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:128
msgctxt "@label"
msgid "This configuration is not available because %1 is not recognized. Please visit %2 to download the correct material profile."
-msgstr ""
+msgstr "Cette configuration n'est pas disponible car %1 n'est pas reconnu. Veuillez visiter %2 pour télécharger le profil matériel correct."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:129
msgctxt "@label"
msgid "Marketplace"
-msgstr ""
+msgstr "Marché en ligne"
#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:15
msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr "Ouvrir un fichier &récent"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr "Activer l'impression"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr "Nom de la tâche"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Durée d'impression"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:169
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr "Durée restante estimée"
#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
msgctxt "@label"
-msgid "View types"
-msgstr ""
+msgid "View type"
+msgstr "Type d'affichage"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
msgctxt "@label"
-msgid "Hi "
-msgstr ""
+msgid "Object list"
+msgstr "Liste d'objets"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:22
+msgctxt "@label The argument is a username."
+msgid "Hi %1"
+msgstr "Bonjour %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:33
msgctxt "@button"
msgid "Ultimaker account"
-msgstr ""
+msgstr "Compte Ultimaker"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
msgctxt "@button"
msgid "Sign out"
-msgstr ""
+msgstr "Déconnexion"
#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
msgctxt "@action:button"
msgid "Sign in"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:29
-msgctxt "@label"
-msgid "Ultimaker Cloud"
-msgstr ""
+msgstr "Se connecter"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
msgctxt "@label"
msgid "The next generation 3D printing workflow"
-msgstr ""
+msgstr "Le flux d'impression 3D de nouvelle génération"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:51
msgctxt "@text"
msgid ""
"- Send print jobs to Ultimaker printers outside your local network\n"
"- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
-"- Get exclusive access to material profiles from leading brands"
+"- Get exclusive access to print profiles from leading brands"
msgstr ""
+"- Envoyez des tâches d'impression à des imprimantes Ultimaker hors de votre réseau local\n"
+"- Stockez vos paramètres Ultimaker Cura dans le cloud pour les utiliser où que vous soyez\n"
+"- Obtenez un accès exclusif aux profils d'impression des principales marques"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
msgctxt "@button"
msgid "Create account"
-msgstr ""
+msgstr "Créer un compte"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
msgctxt "@label"
msgid "No time estimation available"
-msgstr ""
+msgstr "Aucune estimation de la durée n'est disponible"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:76
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
msgctxt "@label"
msgid "No cost estimation available"
-msgstr ""
+msgstr "Aucune estimation des coûts n'est disponible"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
msgctxt "@button"
msgid "Preview"
-msgstr ""
+msgstr "Aperçu"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:55
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Découpe en cours..."
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:61
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:67
msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
+msgid "Unable to slice"
msgstr "Impossible de découper"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:116
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
+msgctxt "@button"
+msgid "Processing"
+msgstr "Traitement"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
msgctxt "@button"
msgid "Slice"
-msgstr ""
+msgstr "Découper"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
msgctxt "@label"
msgid "Start the slicing process"
-msgstr ""
+msgstr "Démarrer le processus de découpe"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
msgctxt "@button"
msgid "Cancel"
-msgstr ""
+msgstr "Annuler"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
msgctxt "@label"
-msgid "Time specification"
-msgstr ""
+msgid "Time estimation"
+msgstr "Estimation de durée"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
msgctxt "@label"
-msgid "Material specification"
-msgstr ""
+msgid "Material estimation"
+msgstr "Estimation du matériau"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
msgctxt "@label m for meter"
@@ -4380,292 +4119,306 @@ msgstr "%1g"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Connected printers"
-msgstr ""
+msgstr "Imprimantes connectées"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Preset printers"
-msgstr ""
+msgstr "Imprimantes préréglées"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
msgctxt "@button"
msgid "Add printer"
-msgstr ""
+msgstr "Ajouter une imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:173
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
msgctxt "@button"
msgid "Manage printers"
-msgstr ""
+msgstr "Gérer les imprimantes"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
msgctxt "@action:inmenu"
msgid "Show Online Troubleshooting Guide"
-msgstr ""
+msgstr "Afficher le guide de dépannage en ligne"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr "Passer en Plein écran"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
+msgctxt "@action:inmenu"
+msgid "Exit Full Screen"
+msgstr "Quitter le mode plein écran"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:103
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Annuler"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:113
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "&Rétablir"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:123
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Quitter"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:131
msgctxt "@action:inmenu menubar:view"
msgid "3D View"
msgstr "Vue 3D"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:138
msgctxt "@action:inmenu menubar:view"
msgid "Front View"
msgstr "Vue de face"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:145
msgctxt "@action:inmenu menubar:view"
msgid "Top View"
msgstr "Vue du dessus"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:152
msgctxt "@action:inmenu menubar:view"
msgid "Left Side View"
msgstr "Vue latérale gauche"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:159
msgctxt "@action:inmenu menubar:view"
msgid "Right Side View"
msgstr "Vue latérale droite"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Configurer Cura..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:173
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Ajouter une imprimante..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:179
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Gérer les &imprimantes..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Gérer les matériaux..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195
msgctxt "@action:inmenu menubar:profile"
msgid "&Update profile with current settings/overrides"
msgstr "&Mettre à jour le profil à l'aide des paramètres / forçages actuels"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:192
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Ignorer les modifications actuelles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr "&Créer un profil à partir des paramètres / forçages actuels..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Gérer les profils..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:229
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Afficher la &documentation en ligne"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:237
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Notifier un &bug"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:245
+msgctxt "@action:inmenu menubar:help"
+msgid "What's New"
+msgstr "Quoi de neuf"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
msgctxt "@action:inmenu menubar:help"
msgid "About..."
msgstr "À propos de..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:258
msgctxt "@action:inmenu menubar:edit"
msgid "Delete Selected Model"
msgid_plural "Delete Selected Models"
msgstr[0] "Supprimer le modèle sélectionné"
msgstr[1] "Supprimer les modèles sélectionnés"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
msgctxt "@action:inmenu menubar:edit"
msgid "Center Selected Model"
msgid_plural "Center Selected Models"
msgstr[0] "Centrer le modèle sélectionné"
msgstr[1] "Centrer les modèles sélectionnés"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
msgctxt "@action:inmenu menubar:edit"
msgid "Multiply Selected Model"
msgid_plural "Multiply Selected Models"
msgstr[0] "Multiplier le modèle sélectionné"
msgstr[1] "Multiplier les modèles sélectionnés"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Supprimer le modèle"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:294
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Ce&ntrer le modèle sur le plateau"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:283
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:300
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "&Grouper les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:303
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:320
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Dégrouper les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:313
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "&Fusionner les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "&Multiplier le modèle..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:347
msgctxt "@action:inmenu menubar:edit"
msgid "Select All Models"
msgstr "Sélectionner tous les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:357
msgctxt "@action:inmenu menubar:edit"
msgid "Clear Build Plate"
msgstr "Supprimer les objets du plateau"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:367
msgctxt "@action:inmenu menubar:file"
msgid "Reload All Models"
msgstr "Recharger tous les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:376
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models To All Build Plates"
msgstr "Réorganiser tous les modèles sur tous les plateaux"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:383
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Réorganiser tous les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:391
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Réorganiser la sélection"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:381
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:398
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr "Réinitialiser toutes les positions des modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:405
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Transformations"
msgstr "Réinitialiser tous les modèles et transformations"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:412
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Ouvrir le(s) fichier(s)..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:420
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Nouveau projet..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:427
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Afficher le dossier de configuration"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
msgid "&Marketplace"
-msgstr ""
+msgstr "&Marché en ligne"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:181
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
msgctxt "@label"
msgid "This package will be installed after restarting."
msgstr "Ce paquet sera installé après le redémarrage."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Paramètres"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:538
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Fermeture de Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:487
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:499
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:551
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr "Êtes-vous sûr de vouloir quitter Cura ?"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:589
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:19
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Ouvrir le(s) fichier(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:632
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:695
msgctxt "@window:title"
msgid "Install Package"
msgstr "Installer le paquet"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:640
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:703
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Ouvrir le(s) fichier(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:643
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:706
msgctxt "@text:window"
msgid "We have found one or more G-Code files within the files you have selected. You can only open one G-Code file at a time. If you want to open a G-Code file, please just select only one."
msgstr "Nous avons trouvé au moins un fichier G-Code parmi les fichiers que vous avez sélectionné. Vous ne pouvez ouvrir qu'un seul fichier G-Code à la fois. Si vous souhaitez ouvrir un fichier G-Code, veuillez ne sélectionner qu'un seul fichier de ce type."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:713
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:18
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:809
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Ajouter une imprimante"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:817
+msgctxt "@title:window"
+msgid "What's New"
+msgstr "Quoi de neuf"
+
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
msgctxt "@label %1 is filled in with the name of an extruder"
msgid "Print Selected Model with %1"
@@ -4727,50 +4480,22 @@ msgctxt "@action:button"
msgid "Create New Profile"
msgstr "Créer un nouveau profil"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:78
-msgctxt "@title:tab"
-msgid "Add a printer to Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:92
-msgctxt "@title:tab"
-msgid ""
-"Select the printer you want to use from the list below.\n"
-"\n"
-"If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:249
-msgctxt "@label"
-msgid "Manufacturer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:271
-msgctxt "@label"
-msgid "Printer Name"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:294
-msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Ajouter une imprimante"
-
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:15
msgctxt "@title:window"
msgid "About Cura"
msgstr "À propos de Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:56
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:57
msgctxt "@label"
msgid "version: %1"
msgstr "version : %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:72
msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing."
msgstr "Solution complète pour l'impression 3D par dépôt de filament fondu."
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:85
msgctxt "@info:credit"
msgid ""
"Cura is developed by Ultimaker B.V. in cooperation with the community.\n"
@@ -4779,122 +4504,122 @@ msgstr ""
"Cura a été développé par Ultimaker B.V. en coopération avec la communauté Ultimaker.\n"
"Cura est fier d'utiliser les projets open source suivants :"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
msgctxt "@label"
msgid "Graphical user interface"
msgstr "Interface utilisateur graphique"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
msgctxt "@label"
msgid "Application framework"
msgstr "Cadre d'application"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
msgctxt "@label"
msgid "G-code generator"
msgstr "Générateur G-Code"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:138
msgctxt "@label"
msgid "Interprocess communication library"
msgstr "Bibliothèque de communication interprocess"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
msgctxt "@label"
msgid "Programming language"
msgstr "Langage de programmation"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
msgctxt "@label"
msgid "GUI framework"
msgstr "Cadre IUG"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
msgctxt "@label"
msgid "GUI framework bindings"
msgstr "Liens cadre IUG"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
msgctxt "@label"
msgid "C/C++ Binding library"
msgstr "Bibliothèque C/C++ Binding"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
msgctxt "@label"
msgid "Data interchange format"
msgstr "Format d'échange de données"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
msgctxt "@label"
msgid "Support library for scientific computing"
msgstr "Prise en charge de la bibliothèque pour le calcul scientifique"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
msgctxt "@label"
msgid "Support library for faster math"
msgstr "Prise en charge de la bibliothèque pour des maths plus rapides"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
msgctxt "@label"
msgid "Support library for handling STL files"
msgstr "Prise en charge de la bibliothèque pour le traitement des fichiers STL"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
msgctxt "@label"
msgid "Support library for handling planar objects"
msgstr "Prise en charge de la bibliothèque pour le traitement des objets planaires"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
msgctxt "@label"
msgid "Support library for handling triangular meshes"
msgstr "Prise en charge de la bibliothèque pour le traitement des mailles triangulaires"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
msgctxt "@label"
msgid "Support library for analysis of complex networks"
msgstr "Prise en charge de la bibliothèque pour l'analyse de réseaux complexes"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
msgctxt "@label"
msgid "Support library for handling 3MF files"
msgstr "Prise en charge de la bibliothèque pour le traitement des fichiers 3MF"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
msgctxt "@label"
msgid "Support library for file metadata and streaming"
msgstr "Prise en charge de la bibliothèque pour les métadonnées et le streaming de fichiers"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
msgctxt "@label"
msgid "Serial communication library"
msgstr "Bibliothèque de communication série"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
msgctxt "@label"
msgid "ZeroConf discovery library"
msgstr "Bibliothèque de découverte ZeroConf"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
msgctxt "@label"
msgid "Polygon clipping library"
msgstr "Bibliothèque de découpe polygone"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:156
msgctxt "@Label"
msgid "Python HTTP library"
msgstr "Bibliothèque Python HTTP"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
msgctxt "@label"
msgid "Font"
msgstr "Police"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
msgctxt "@label"
msgid "SVG icons"
msgstr "Icônes SVG"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:160
msgctxt "@label"
msgid "Linux cross-distribution application deployment"
msgstr "Déploiement d'applications sur multiples distributions Linux"
@@ -4914,27 +4639,27 @@ msgctxt "@title:window"
msgid "Save Project"
msgstr "Enregistrer le projet"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:138
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:177
msgctxt "@action:label"
msgid "Extruder %1"
msgstr "Extrudeuse %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:192
msgctxt "@action:label"
msgid "%1 & material"
msgstr "%1 & matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:243
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:194
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:label"
msgid "Don't show project summary on save again"
msgstr "Ne pas afficher à nouveau le résumé du projet lors de l'enregistrement"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:262
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:302
msgctxt "@action:button"
msgid "Save"
msgstr "Enregistrer"
@@ -4964,30 +4689,1451 @@ msgctxt "@action:button"
msgid "Import models"
msgstr "Importer les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:210
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Afficher uniquement le plateau actuel"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
+msgctxt "@label"
+msgid "Empty"
+msgstr "Vide"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:226
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "Réorganiser sur tous les plateaux"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
+msgctxt "@label"
+msgid "Add a printer"
+msgstr "Ajouter une imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:246
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "Réorganiser le plateau actuel"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
+msgctxt "@label"
+msgid "Add a networked printer"
+msgstr "Ajouter une imprimante en réseau"
-#: X3GWriter/plugin.json
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
+msgctxt "@label"
+msgid "Add a non-networked printer"
+msgstr "Ajouter une imprimante hors réseau"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:70
+msgctxt "@label"
+msgid "Add printer by IP address"
+msgstr "Ajouter une imprimante par adresse IP"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:133
+msgctxt "@text"
+msgid "Place enter your printer's IP address."
+msgstr "Saisissez l'adresse IP de votre imprimante."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Ajouter"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:204
+msgctxt "@label"
+msgid "Could not connect to device."
+msgstr "Impossible de se connecter à l'appareil."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:208
+msgctxt "@label"
+msgid "The printer at this address has not responded yet."
+msgstr "L'imprimante à cette adresse n'a pas encore répondu."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:240
+msgctxt "@label"
+msgid "This printer cannot be added because it's an unknown printer or it's not the host of a group."
+msgstr "Cette imprimante ne peut pas être ajoutée parce qu'il s'agit d'une imprimante inconnue ou de l'hôte d'un groupe."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:329
+msgctxt "@button"
+msgid "Back"
+msgstr "Précédent"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:342
+msgctxt "@button"
+msgid "Connect"
+msgstr "Se connecter"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/FirstStartMachineActionsContent.qml:77
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:123
+msgctxt "@button"
+msgid "Next"
+msgstr "Suivant"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:23
+msgctxt "@label"
+msgid "User Agreement"
+msgstr "Accord utilisateur"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:56
+msgctxt "@button"
+msgid "Agree"
+msgstr "Accepter"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:70
+msgctxt "@button"
+msgid "Decline and close"
+msgstr "Décliner et fermer"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:24
+msgctxt "@label"
+msgid "Help us to improve Ultimaker Cura"
+msgstr "Aidez-nous à améliorer Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:57
+msgctxt "@text"
+msgid "Ultimaker Cura collects anonymous data to improve print quality and user experience, including:"
+msgstr "Ultimaker Cura recueille des données anonymes pour améliorer la qualité d'impression et l'expérience utilisateur, notamment :"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:71
+msgctxt "@text"
+msgid "Machine types"
+msgstr "Types de machines"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:77
+msgctxt "@text"
+msgid "Material usage"
+msgstr "Utilisation du matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:83
+msgctxt "@text"
+msgid "Number of slices"
+msgstr "Nombre de découpes"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:89
+msgctxt "@text"
+msgid "Print settings"
+msgstr "Paramètres d'impression"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:102
+msgctxt "@text"
+msgid "Data collected by Ultimaker Cura will not contain any personal information."
+msgstr "Les données recueillies par Ultimaker Cura ne contiendront aucun renseignement personnel."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:103
+msgctxt "@text"
+msgid "More information"
+msgstr "Plus d'informations"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WhatsNewContent.qml:24
+msgctxt "@label"
+msgid "What's new in Ultimaker Cura"
+msgstr "Quoi de neuf dans Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:42
+msgctxt "@label"
+msgid "There is no printer found over your network."
+msgstr "Aucune imprimante n'a été trouvée sur votre réseau."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:179
+msgctxt "@label"
+msgid "Refresh"
+msgstr "Rafraîchir"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:190
+msgctxt "@label"
+msgid "Add printer by IP"
+msgstr "Ajouter une imprimante par IP"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:223
+msgctxt "@label"
+msgid "Troubleshooting"
+msgstr "Dépannage"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:211
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Nom de l'imprimante"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:224
+msgctxt "@text"
+msgid "Please give your printer a name"
+msgstr "Veuillez donner un nom à votre imprimante"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:36
+msgctxt "@label"
+msgid "Ultimaker Cloud"
+msgstr "Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:77
+msgctxt "@text"
+msgid "The next generation 3D printing workflow"
+msgstr "Le flux d'impression 3D de nouvelle génération"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:94
+msgctxt "@text"
+msgid "- Send print jobs to Ultimaker printers outside your local network"
+msgstr "- Envoyez des tâches d'impression à des imprimantes Ultimaker hors de votre réseau local"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:97
+msgctxt "@text"
+msgid "- Store your Ultimaker Cura settings in the cloud for use anywhere"
+msgstr "- Stockez vos paramètres Ultimaker Cura dans le cloud pour les utiliser où que vous soyez"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:100
+msgctxt "@text"
+msgid "- Get exclusive access to print profiles from leading brands"
+msgstr "- Accédez en exclusivité aux profils d'impression des plus grandes marques"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:119
+msgctxt "@button"
+msgid "Finish"
+msgstr "Fin"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:128
+msgctxt "@button"
+msgid "Create an account"
+msgstr "Créer un compte"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:29
+msgctxt "@label"
+msgid "Welcome to Ultimaker Cura"
+msgstr "Bienvenue dans Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:47
+msgctxt "@text"
+msgid ""
+"Please follow these steps to set up\n"
+"Ultimaker Cura. This will only take a few moments."
+msgstr ""
+"Veuillez suivre ces étapes pour configurer\n"
+"Ultimaker Cura. Cela ne prendra que quelques instants."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:58
+msgctxt "@button"
+msgid "Get started"
+msgstr "Prise en main"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:27
+msgctxt "@info:tooltip"
+msgid "3D View"
+msgstr "Vue 3D"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:40
+msgctxt "@info:tooltip"
+msgid "Front View"
+msgstr "Vue de face"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
+msgctxt "@info:tooltip"
+msgid "Top View"
+msgstr "Vue du dessus"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
+msgctxt "@info:tooltip"
+msgid "Left View"
+msgstr "Vue gauche"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:79
+msgctxt "@info:tooltip"
+msgid "Right View"
+msgstr "Vue droite"
+
+#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
-msgstr "Permet de sauvegarder la tranche résultante sous forme de fichier X3G, pour prendre en charge les imprimantes qui lisent ce format (Malyan, Makerbot et autres imprimantes basées sur Sailfish)."
+msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
+msgstr "Permet de modifier les paramètres de la machine (tels que volume d'impression, taille de buse, etc.)"
-#: X3GWriter/plugin.json
+#: MachineSettingsAction/plugin.json
msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3GWriter"
+msgid "Machine Settings action"
+msgstr "Action Paramètres de la machine"
+
+#: Toolbox/plugin.json
+msgctxt "description"
+msgid "Find, manage and install new Cura packages."
+msgstr "Rechercher, gérer et installer de nouveaux paquets Cura."
+
+#: Toolbox/plugin.json
+msgctxt "name"
+msgid "Toolbox"
+msgstr "Boîte à outils"
+
+#: XRayView/plugin.json
+msgctxt "description"
+msgid "Provides the X-Ray view."
+msgstr "Permet la vue Rayon-X."
+
+#: XRayView/plugin.json
+msgctxt "name"
+msgid "X-Ray View"
+msgstr "Vue Rayon-X"
+
+#: X3DReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading X3D files."
+msgstr "Fournit la prise en charge de la lecture de fichiers X3D."
+
+#: X3DReader/plugin.json
+msgctxt "name"
+msgid "X3D Reader"
+msgstr "Lecteur X3D"
+
+#: GCodeWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a file."
+msgstr "Enregistre le G-Code dans un fichier."
+
+#: GCodeWriter/plugin.json
+msgctxt "name"
+msgid "G-code Writer"
+msgstr "Générateur de G-Code"
+
+#: ModelChecker/plugin.json
+msgctxt "description"
+msgid "Checks models and print configuration for possible printing issues and give suggestions."
+msgstr "Vérifie les modèles et la configuration de l'impression pour déceler d'éventuels problèmes d'impression et donne des suggestions."
+
+#: ModelChecker/plugin.json
+msgctxt "name"
+msgid "Model Checker"
+msgstr "Contrôleur de modèle"
+
+#: FirmwareUpdater/plugin.json
+msgctxt "description"
+msgid "Provides a machine actions for updating firmware."
+msgstr "Fournit à une machine des actions permettant la mise à jour du firmware."
+
+#: FirmwareUpdater/plugin.json
+msgctxt "name"
+msgid "Firmware Updater"
+msgstr "Programme de mise à jour du firmware"
+
+#: AMFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading AMF files."
+msgstr "Fournit la prise en charge de la lecture de fichiers AMF."
+
+#: AMFReader/plugin.json
+msgctxt "name"
+msgid "AMF Reader"
+msgstr "Lecteur AMF"
+
+#: USBPrinting/plugin.json
+msgctxt "description"
+msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
+msgstr "Accepte les G-Code et les envoie à une imprimante. Ce plugin peut aussi mettre à jour le firmware."
+
+#: USBPrinting/plugin.json
+msgctxt "name"
+msgid "USB printing"
+msgstr "Impression par USB"
+
+#: GCodeGzWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a compressed archive."
+msgstr "Enregistre le G-Code dans une archive compressée."
+
+#: GCodeGzWriter/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Writer"
+msgstr "Générateur de G-Code compressé"
+
+#: UFPWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing Ultimaker Format Packages."
+msgstr "Permet l'écriture de fichiers Ultimaker Format Package."
+
+#: UFPWriter/plugin.json
+msgctxt "name"
+msgid "UFP Writer"
+msgstr "Générateur UFP"
+
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Fournit une étape de préparation dans Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Étape de préparation"
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "description"
+msgid "Provides removable drive hotplugging and writing support."
+msgstr "Permet le branchement hot-plug et l'écriture sur lecteur amovible."
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "name"
+msgid "Removable Drive Output Device Plugin"
+msgstr "Plugin de périphérique de sortie sur disque amovible"
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "description"
+msgid "Manages network connections to Ultimaker networked printers."
+msgstr "Gère les connexions réseau vers les imprimantes Ultimaker en réseau."
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "name"
+msgid "Ultimaker Network Connection"
+msgstr "Connexion réseau Ultimaker"
+
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Fournit une étape de surveillance dans Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Étape de surveillance"
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "description"
+msgid "Checks for firmware updates."
+msgstr "Vérifie les mises à jour du firmware."
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "name"
+msgid "Firmware Update Checker"
+msgstr "Vérificateur des mises à jour du firmware"
+
+#: SimulationView/plugin.json
+msgctxt "description"
+msgid "Provides the Simulation view."
+msgstr "Fournit la Vue simulation."
+
+#: SimulationView/plugin.json
+msgctxt "name"
+msgid "Simulation View"
+msgstr "Vue simulation"
+
+#: GCodeGzReader/plugin.json
+msgctxt "description"
+msgid "Reads g-code from a compressed archive."
+msgstr "Lit le G-Code à partir d'une archive compressée."
+
+#: GCodeGzReader/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Reader"
+msgstr "Lecteur G-Code compressé"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "description"
+msgid "Extension that allows for user created scripts for post processing"
+msgstr "Extension qui permet le post-traitement des scripts créés par l'utilisateur"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "name"
+msgid "Post Processing"
+msgstr "Post-traitement"
+
+#: SupportEraser/plugin.json
+msgctxt "description"
+msgid "Creates an eraser mesh to block the printing of support in certain places"
+msgstr "Crée un maillage effaceur pour bloquer l'impression du support en certains endroits"
+
+#: SupportEraser/plugin.json
+msgctxt "name"
+msgid "Support Eraser"
+msgstr "Effaceur de support"
+
+#: UFPReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading Ultimaker Format Packages."
+msgstr "Fournit un support pour la lecture des paquets de format Ultimaker."
+
+#: UFPReader/plugin.json
+msgctxt "name"
+msgid "UFP Reader"
+msgstr "Lecteur UFP"
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "description"
+msgid "Submits anonymous slice info. Can be disabled through preferences."
+msgstr "Envoie des informations anonymes sur le découpage. Peut être désactivé dans les préférences."
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "name"
+msgid "Slice info"
+msgstr "Information sur le découpage"
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "description"
+msgid "Provides capabilities to read and write XML-based material profiles."
+msgstr "Offre la possibilité de lire et d'écrire des profils matériels basés sur XML."
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "name"
+msgid "Material Profiles"
+msgstr "Profils matériels"
+
+#: LegacyProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from legacy Cura versions."
+msgstr "Fournit la prise en charge de l'importation de profils à partir de versions Cura antérieures."
+
+#: LegacyProfileReader/plugin.json
+msgctxt "name"
+msgid "Legacy Cura Profile Reader"
+msgstr "Lecteur de profil Cura antérieur"
+
+#: GCodeProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from g-code files."
+msgstr "Fournit la prise en charge de l'importation de profils à partir de fichiers g-code."
+
+#: GCodeProfileReader/plugin.json
+msgctxt "name"
+msgid "G-code Profile Reader"
+msgstr "Lecteur de profil G-Code"
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
+msgstr "Configurations des mises à niveau de Cura 3.2 vers Cura 3.3."
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.2 to 3.3"
+msgstr "Mise à niveau de 3.2 vers 3.3"
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
+msgstr "Configurations des mises à niveau de Cura 3.3 vers Cura 3.4."
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.3 to 3.4"
+msgstr "Mise à niveau de 3.3 vers 3.4"
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.3 to Cura 4.4."
+msgstr "Configurations des mises à niveau de Cura 4.3 vers Cura 4.4."
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.3 to 4.4"
+msgstr "Mise à niveau de 4.3 vers 4.4"
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
+msgstr "Configurations des mises à niveau de Cura 2.5 vers Cura 2.6."
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.5 to 2.6"
+msgstr "Mise à niveau de 2.5 vers 2.6"
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
+msgstr "Met à niveau les configurations, de Cura 2.7 vers Cura 3.0."
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.7 to 3.0"
+msgstr "Mise à niveau de version, de 2.7 vers 3.0"
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.5 to Cura 4.0."
+msgstr "Configurations des mises à niveau de Cura 3.5 vers Cura 4.0."
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.5 to 4.0"
+msgstr "Mise à niveau de 3.5 vers 4.0"
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
+msgstr "Configurations des mises à niveau de Cura 3.4 vers Cura 3.5."
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.4 to 3.5"
+msgstr "Mise à niveau de 3.4 vers 3.5"
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.0 to Cura 4.1."
+msgstr "Configurations des mises à niveau de Cura 4.0 vers Cura 4.1."
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.0 to 4.1"
+msgstr "Mise à niveau de 4.0 vers 4.1"
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
+msgstr "Met à niveau les configurations, de Cura 3.0 vers Cura 3.1."
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.0 to 3.1"
+msgstr "Mise à niveau de version, de 3.0 vers 3.1"
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.1 to Cura 4.2."
+msgstr "Configurations des mises à jour de Cura 4.1 vers Cura 4.2."
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.1 to 4.2"
+msgstr "Mise à jour de 4.1 vers 4.2"
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
+msgstr "Configurations des mises à niveau de Cura 2.6 vers Cura 2.7."
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.6 to 2.7"
+msgstr "Mise à niveau de 2.6 vers 2.7"
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
+msgstr "Configurations des mises à niveau de Cura 2.1 vers Cura 2.2."
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.1 to 2.2"
+msgstr "Mise à niveau vers 2.1 vers 2.2"
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
+msgstr "Configurations des mises à niveau de Cura 2.2 vers Cura 2.4."
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.2 to 2.4"
+msgstr "Mise à niveau de 2.2 vers 2.4"
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.2 to Cura 4.3."
+msgstr "Configurations des mises à jour de Cura 4.2 vers Cura 4.3."
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.2 to 4.3"
+msgstr "Mise à jour de 4.2 vers 4.3"
+
+#: ImageReader/plugin.json
+msgctxt "description"
+msgid "Enables ability to generate printable geometry from 2D image files."
+msgstr "Permet de générer une géométrie imprimable à partir de fichiers d'image 2D."
+
+#: ImageReader/plugin.json
+msgctxt "name"
+msgid "Image Reader"
+msgstr "Lecteur d'images"
+
+#: TrimeshReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading model files."
+msgstr "Fournit la prise en charge de la lecture de fichiers modèle 3D."
+
+#: TrimeshReader/plugin.json
+msgctxt "name"
+msgid "Trimesh Reader"
+msgstr "Lecteur de Trimesh"
+
+#: CuraEngineBackend/plugin.json
+msgctxt "description"
+msgid "Provides the link to the CuraEngine slicing backend."
+msgstr "Fournit le lien vers l'arrière du système de découpage CuraEngine."
+
+#: CuraEngineBackend/plugin.json
+msgctxt "name"
+msgid "CuraEngine Backend"
+msgstr "Système CuraEngine"
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "description"
+msgid "Provides the Per Model Settings."
+msgstr "Fournit les paramètres par modèle."
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "name"
+msgid "Per Model Settings Tool"
+msgstr "Outil de paramètres par modèle"
+
+#: 3MFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading 3MF files."
+msgstr "Fournit la prise en charge de la lecture de fichiers 3MF."
+
+#: 3MFReader/plugin.json
+msgctxt "name"
+msgid "3MF Reader"
+msgstr "Lecteur 3MF"
+
+#: SolidView/plugin.json
+msgctxt "description"
+msgid "Provides a normal solid mesh view."
+msgstr "Affiche une vue en maille solide normale."
+
+#: SolidView/plugin.json
+msgctxt "name"
+msgid "Solid View"
+msgstr "Vue solide"
+
+#: GCodeReader/plugin.json
+msgctxt "description"
+msgid "Allows loading and displaying G-code files."
+msgstr "Permet le chargement et l'affichage de fichiers G-Code."
+
+#: GCodeReader/plugin.json
+msgctxt "name"
+msgid "G-code Reader"
+msgstr "Lecteur G-Code"
+
+#: CuraDrive/plugin.json
+msgctxt "description"
+msgid "Backup and restore your configuration."
+msgstr "Sauvegardez et restaurez votre configuration."
+
+#: CuraDrive/plugin.json
+msgctxt "name"
+msgid "Cura Backups"
+msgstr "Sauvegardes Cura"
+
+#: CuraProfileWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for exporting Cura profiles."
+msgstr "Fournit la prise en charge de l'exportation de profils Cura."
+
+#: CuraProfileWriter/plugin.json
+msgctxt "name"
+msgid "Cura Profile Writer"
+msgstr "Générateur de profil Cura"
+
+#: 3MFWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing 3MF files."
+msgstr "Permet l'écriture de fichiers 3MF."
+
+#: 3MFWriter/plugin.json
+msgctxt "name"
+msgid "3MF Writer"
+msgstr "Générateur 3MF"
+
+#: PreviewStage/plugin.json
+msgctxt "description"
+msgid "Provides a preview stage in Cura."
+msgstr "Fournit une étape de prévisualisation dans Cura."
+
+#: PreviewStage/plugin.json
+msgctxt "name"
+msgid "Preview Stage"
+msgstr "Étape de prévisualisation"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "description"
+msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
+msgstr "Fournit les actions de la machine pour les machines Ultimaker (telles que l'assistant de calibration du plateau, sélection des mises à niveau, etc.)"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "name"
+msgid "Ultimaker machine actions"
+msgstr "Actions de la machine Ultimaker"
+
+#: CuraProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing Cura profiles."
+msgstr "Fournit la prise en charge de l'importation de profils Cura."
+
+#: CuraProfileReader/plugin.json
+msgctxt "name"
+msgid "Cura Profile Reader"
+msgstr "Lecteur de profil Cura"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Flatten active settings"
+#~ msgstr "Aplatir les paramètres actifs"
+
+#~ msgctxt "@info:status"
+#~ msgid "Profile has been flattened & activated."
+#~ msgstr "Le profil a été aplati et activé."
+
+#~ msgctxt "X3g Writer Plugin Description"
+#~ msgid "Writes X3g to files"
+#~ msgstr "Écrit X3G dans des fichiers"
+
+#~ msgctxt "X3g Writer File Description"
+#~ msgid "X3g File"
+#~ msgstr "Fichier X3G"
+
+#~ msgctxt "X3G Writer File Description"
+#~ msgid "X3G File"
+#~ msgstr "Fichier X3G"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Open Compressed Triangle Mesh"
+#~ msgstr "Ouvrir le maillage triangulaire compressé"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Profile Assistant"
+#~ msgstr "Assistant de profil"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Profile Assistant"
+#~ msgstr "Assistant de profil"
+
+#~ msgctxt "@action:button"
+#~ msgid "Retry"
+#~ msgstr "Réessayer"
+
+#~ msgctxt "@label:table_header"
+#~ msgid "Print Core"
+#~ msgstr "Print Core"
+
+#~ msgctxt "@label"
+#~ msgid "Don't support overlap with other models"
+#~ msgstr "Ne pas prendre en charge le chevauchement avec d'autres modèles"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for overlap with other models"
+#~ msgstr "Modifier les paramètres de chevauchement avec d'autres modèles"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for infill of other models"
+#~ msgstr "Modifier les paramètres de remplissage d'autres modèles"
+
+#~ msgctxt "@action:ComboBox option"
+#~ msgid "Update existing"
+#~ msgstr "Mettre à jour l'existant"
+
+#~ msgctxt "@label"
+#~ msgid "Not supported"
+#~ msgstr "Non pris en charge"
+
+#~ msgctxt "@action:button"
+#~ msgid "Previous"
+#~ msgstr "Précédent"
+
+#~ msgctxt "@label"
+#~ msgid "Tip"
+#~ msgstr "Astuce"
+
+#~ msgctxt "@label"
+#~ msgid "Print experiment"
+#~ msgstr "Test d'impression"
+
+#~ msgctxt "@label"
+#~ msgid "Checklist"
+#~ msgstr "Liste de contrôle"
+
+#~ msgctxt "@label"
+#~ msgid "Please select any upgrades made to this Ultimaker 2."
+#~ msgstr "Sélectionnez les mises à niveau disponibles pour cet Ultimaker 2."
+
+#~ msgctxt "@label"
+#~ msgid "Olsson Block"
+#~ msgstr "Blocage Olsson"
+
+#~ msgctxt "@window:text"
+#~ msgid "Camera rendering: "
+#~ msgstr "Rendu caméra : "
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Use multi build plate functionality"
+#~ msgstr "Utiliser la fonctionnalité multi-plateau"
+
+#~ msgctxt "@option:check"
+#~ msgid "Use multi build plate functionality (restart required)"
+#~ msgstr "Utiliser la fonctionnalité multi-plateau (redémarrage requis)"
+
+#~ msgctxt "@label"
+#~ msgid "Default profiles"
+#~ msgstr "Profils par défaut"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "search settings"
+#~ msgstr "paramètres de recherche"
+
+#~ msgctxt "@label"
+#~ msgid "Layer Height"
+#~ msgstr "Hauteur de la couche"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile."
+#~ msgstr "Ce profil de qualité n'est pas disponible pour votre matériau et configuration des buses actuels. Veuillez modifier ces derniers pour activer ce profil de qualité."
+
+#~ msgctxt "@tooltip"
+#~ msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
+#~ msgstr "Un profil personnalisé est actuellement actif. Pour activer le curseur de qualité, choisissez un profil de qualité par défaut dans l'onglet Personnaliser"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Build plate"
+#~ msgstr "Plateau"
+
+#~ msgctxt "@title:settings"
+#~ msgid "&Profile"
+#~ msgstr "&Profil"
+
+#~ msgctxt "@action:label"
+#~ msgid "Build plate"
+#~ msgstr "Plateau"
+
+#~ msgctxt "description"
+#~ msgid "Dump the contents of all settings to a HTML file."
+#~ msgstr "Exporter les contenus de tous les paramètres vers un fichier HTML."
+
+#~ msgctxt "name"
+#~ msgid "God Mode"
+#~ msgstr "Mode God"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattened quality changes profile."
+#~ msgstr "Créer un profil de changements de qualité aplati."
+
+#~ msgctxt "name"
+#~ msgid "Profile Flattener"
+#~ msgstr "Aplatisseur de profil"
+
+#~ msgctxt "description"
+#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+#~ msgstr "Permet aux fabricants de matériaux de créer de nouveaux matériaux et profils de qualité à l'aide d'une interface utilisateur ad hoc."
+
+#~ msgctxt "name"
+#~ msgid "Print Profile Assistant"
+#~ msgstr "Assistant de profil d'impression"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network."
+#~ msgstr "Connecté sur le réseau."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. Please approve the access request on the printer."
+#~ msgstr "Connecté sur le réseau. Veuillez approuver la demande d'accès sur l'imprimante."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. No access to control the printer."
+#~ msgstr "Connecté sur le réseau. Pas d'accès pour commander l'imprimante."
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer requested. Please approve the request on the printer"
+#~ msgstr "Accès à l'imprimante demandé. Veuillez approuver la demande sur l'imprimante"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication status"
+#~ msgstr "Statut d'authentification"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication Status"
+#~ msgstr "Statut d'authentification"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Re-send the access request"
+#~ msgstr "Renvoyer la demande d'accès"
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer accepted"
+#~ msgstr "Accès à l'imprimante accepté"
+
+#~ msgctxt "@info:status"
+#~ msgid "No access to print with this printer. Unable to send print job."
+#~ msgstr "Aucun accès pour imprimer avec cette imprimante. Impossible d'envoyer la tâche d'impression."
+
+#~ msgctxt "@action:button"
+#~ msgid "Request Access"
+#~ msgstr "Demande d'accès"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Send access request to the printer"
+#~ msgstr "Envoyer la demande d'accès à l'imprimante"
+
+#~ msgctxt "@label"
+#~ msgid "Unable to start a new print job."
+#~ msgstr "Impossible de démarrer une nouvelle tâche d'impression."
+
+#~ msgctxt "@label"
+#~ msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
+#~ msgstr "Un problème avec la configuration de votre Ultimaker empêche le démarrage de l'impression. Veuillez résoudre ce problème avant de continuer."
+
+#~ msgctxt "@window:title"
+#~ msgid "Mismatched configuration"
+#~ msgstr "Configuration différente"
+
+#~ msgctxt "@label"
+#~ msgid "Are you sure you wish to print with the selected configuration?"
+#~ msgstr "Êtes-vous sûr(e) de vouloir imprimer avec la configuration sélectionnée ?"
+
+#~ msgctxt "@label"
+#~ msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Problème de compatibilité entre la configuration ou l'étalonnage de l'imprimante et Cura. Pour un résultat optimal, découpez toujours pour les PrintCores et matériaux insérés dans votre imprimante."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
+#~ msgstr "Envoi de nouvelles tâches (temporairement) bloqué, envoi de la tâche d'impression précédente en cours."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to printer"
+#~ msgstr "Envoi des données à l'imprimante"
+
+#~ msgctxt "@info:title"
+#~ msgid "Sending Data"
+#~ msgstr "Envoi des données"
+
+#~ msgctxt "@info:status"
+#~ msgid "No Printcore loaded in slot {slot_number}"
+#~ msgstr "Pas de PrintCore inséré dans la fente {slot_number}"
+
+#~ msgctxt "@info:status"
+#~ msgid "No material loaded in slot {slot_number}"
+#~ msgstr "Aucun matériau inséré dans la fente {slot_number}"
+
+#~ msgctxt "@label"
+#~ msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
+#~ msgstr "PrintCore différent (Cura : {cura_printcore_name}, Imprimante : {remote_printcore_name}) sélectionné pour l'extrudeuse {extruder_id}"
+
+#~ msgctxt "@label"
+#~ msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
+#~ msgstr "Matériau différent (Cura : {0}, Imprimante : {1}) sélectionné pour l'extrudeuse {2}"
+
+#~ msgctxt "@window:title"
+#~ msgid "Sync with your printer"
+#~ msgstr "Synchroniser avec votre imprimante"
+
+#~ msgctxt "@label"
+#~ msgid "Would you like to use your current printer configuration in Cura?"
+#~ msgstr "Voulez-vous utiliser votre configuration d'imprimante actuelle dans Cura ?"
+
+#~ msgctxt "@label"
+#~ msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Les PrintCores et / ou matériaux sur votre imprimante diffèrent de ceux de votre projet actuel. Pour un résultat optimal, découpez toujours pour les PrintCores et matériaux insérés dans votre imprimante."
+
+#~ msgctxt "@action:button"
+#~ msgid "View in Monitor"
+#~ msgstr "Afficher sur le moniteur"
+
+#~ msgctxt "@info:status"
+#~ msgid "Printer '{printer_name}' has finished printing '{job_name}'."
+#~ msgstr "{printer_name} a terminé d'imprimer '{job_name}'."
+
+#~ msgctxt "@info:status"
+#~ msgid "The print job '{job_name}' was finished."
+#~ msgstr "La tâche d'impression '{job_name}' est terminée."
+
+#~ msgctxt "@info:status"
+#~ msgid "Print finished"
+#~ msgstr "Impression terminée"
+
+#~ msgctxt "@label:material"
+#~ msgid "Empty"
+#~ msgstr "Vide"
+
+#~ msgctxt "@label:material"
+#~ msgid "Unknown"
+#~ msgstr "Inconnu"
+
+#~ msgctxt "@info:title"
+#~ msgid "Cloud error"
+#~ msgstr "Erreur de cloud"
+
+#~ msgctxt "@info:status"
+#~ msgid "Could not export print job."
+#~ msgstr "Impossible d'exporter la tâche d'impression."
+
+#~ msgctxt "@info:description"
+#~ msgid "There was an error connecting to the cloud."
+#~ msgstr "Une erreur s'est produite lors de la connexion au cloud."
+
+#~ msgctxt "@info:status"
+#~ msgid "Uploading via Ultimaker Cloud"
+#~ msgstr "Téléchargement via Ultimaker Cloud"
+
+#~ msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Se connecter à Ultimaker Cloud"
+
+#~ msgctxt "@action"
+#~ msgid "Don't ask me again for this printer."
+#~ msgstr "Ne plus me demander pour cette imprimante."
+
+#~ msgctxt "@info:status"
+#~ msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
+#~ msgstr "Vous pouvez maintenant lancer et surveiller des impressions où que vous soyez avec votre compte Ultimaker."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected!"
+#~ msgstr "Connecté !"
+
+#~ msgctxt "@action"
+#~ msgid "Review your connection"
+#~ msgstr "Consulter votre connexion"
+
+#~ msgctxt "@info:status Don't translate the XML tags !"
+#~ msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
+#~ msgstr "La machine définie dans le profil {0} ({1}) ne correspond pas à votre machine actuelle ({2}) ; échec de l'importation."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}:"
+#~ msgstr "Échec de l'importation du profil depuis le fichier {0} :"
+
+#~ msgctxt "@window:title"
+#~ msgid "Existing Connection"
+#~ msgstr "Connexion existante"
+
+#~ msgctxt "@message:text"
+#~ msgid "This printer/group is already added to Cura. Please select another printer/group."
+#~ msgstr "Ce groupe / cette imprimante a déjà été ajouté à Cura. Veuillez sélectionner un autre groupe / imprimante."
+
+#~ msgctxt "@label"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Saisissez l'adresse IP ou le nom d'hôte de votre imprimante sur le réseau."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Connect to a printer"
+#~ msgstr "Connecter à une imprimante"
+
+#~ msgctxt "@title"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Guide des paramètres de Cura"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Zooming towards the mouse is not supported in the orthogonal perspective."
+#~ msgstr "Zoom vers la souris n'est pas pris en charge dans la perspective orthogonale."
+
+#~ msgid "Orthogonal"
+#~ msgstr "Orthogonale"
+
+#~ msgctxt "description"
+#~ msgid "Manages network connections to Ultimaker 3 printers."
+#~ msgstr "Gère les connexions réseau vers les imprimantes Ultimaker 3."
+
+#~ msgctxt "name"
+#~ msgid "UM3 Network Connection"
+#~ msgstr "Connexion au réseau UM3"
+
+#~ msgctxt "description"
+#~ msgid "Provides extra information and explanations about settings in Cura, with images and animations."
+#~ msgstr "Fournit des informations et explications supplémentaires sur les paramètres de Cura, avec des images et des animations."
+
+#~ msgctxt "name"
+#~ msgid "Settings Guide"
+#~ msgstr "Guide des paramètres"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Guide des paramètres de Cura"
+
+#~ msgctxt "@info:generic"
+#~ msgid "Settings have been changed to match the current availability of extruders: [%s]"
+#~ msgstr "Les paramètres ont été modifiés pour correspondre aux extrudeuses actuellement disponibles : [%s]"
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "User description"
+#~ msgstr "Description de l'utilisateur"
+
+#~ msgctxt "@info"
+#~ msgid "These options are not available because you are monitoring a cloud printer."
+#~ msgstr "Ces options ne sont pas disponibles car vous surveillez une imprimante cloud."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Go to Cura Connect"
+#~ msgstr "Aller à Cura Connect"
+
+#~ msgctxt "@info"
+#~ msgid "All jobs are printed."
+#~ msgstr "Toutes les tâches ont été imprimées."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "View print history"
+#~ msgstr "Voir l'historique d'impression"
+
+#~ msgctxt "@label"
+#~ msgid ""
+#~ "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
+#~ "\n"
+#~ "Select your printer from the list below:"
+#~ msgstr ""
+#~ "Pour imprimer directement sur votre imprimante sur le réseau, assurez-vous que votre imprimante est connectée au réseau via un câble réseau ou en connectant votre imprimante à votre réseau Wi-Fi. Si vous ne connectez pas Cura avec votre imprimante, vous pouvez utiliser une clé USB pour transférer les fichiers g-code sur votre imprimante.\n"
+#~ "\n"
+#~ "Sélectionnez votre imprimante dans la liste ci-dessous :"
+
+#~ msgctxt "@info"
+#~ msgid ""
+#~ "Please make sure your printer has a connection:\n"
+#~ "- Check if the printer is turned on.\n"
+#~ "- Check if the printer is connected to the network."
+#~ msgstr ""
+#~ "Assurez-vous que votre imprimante est connectée :\n"
+#~ "- Vérifiez si l'imprimante est sous tension.\n"
+#~ "- Vérifiez si l'imprimante est connectée au réseau."
+
+#~ msgctxt "@option:check"
+#~ msgid "See only current build plate"
+#~ msgstr "Afficher uniquement le plateau actuel"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange to all build plates"
+#~ msgstr "Réorganiser sur tous les plateaux"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange current build plate"
+#~ msgstr "Réorganiser le plateau actuel"
+
+#~ msgctxt "description"
+#~ msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
+#~ msgstr "Permet de sauvegarder la tranche résultante sous forme de fichier X3G, pour prendre en charge les imprimantes qui lisent ce format (Malyan, Makerbot et autres imprimantes basées sur Sailfish)."
+
+#~ msgctxt "name"
+#~ msgid "X3GWriter"
+#~ msgstr "X3GWriter"
+
+#~ msgctxt "description"
+#~ msgid "Reads SVG files as toolpaths, for debugging printer movements."
+#~ msgstr "Lit les fichiers SVG comme des Toolpaths, pour déboguer les mouvements de l'imprimante."
+
+#~ msgctxt "name"
+#~ msgid "SVG Toolpath Reader"
+#~ msgstr "Lecteur de Toolpaths SVG"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Changelog"
+#~ msgstr "Récapitulatif des changements"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Show Changelog"
+#~ msgstr "Afficher le récapitulatif des changements"
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to remote cluster"
+#~ msgstr "Envoi de données à un cluster distant"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Se connecter à Ultimaker Cloud"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymized usage statistics."
+#~ msgstr "Cura recueille des statistiques d'utilisation anonymes."
+
+#~ msgctxt "@info:title"
+#~ msgid "Collecting Data"
+#~ msgstr "Collecte des données"
+
+#~ msgctxt "@action:button"
+#~ msgid "More info"
+#~ msgstr "Plus d'informations"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "See more information on what data Cura sends."
+#~ msgstr "Voir plus d'informations sur les données envoyées par Cura."
+
+#~ msgctxt "@action:button"
+#~ msgid "Allow"
+#~ msgstr "Autoriser"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
+#~ msgstr "Autoriser Cura à envoyer des statistiques d'utilisation anonymes pour mieux prioriser les améliorations futures apportées à Cura. Certaines de vos préférences et paramètres sont envoyés, ainsi que la version du logiciel Cura et un hachage des modèles que vous découpez."
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Evaluation"
+#~ msgstr "Évaluation"
+
+#~ msgctxt "@info:title"
+#~ msgid "Network enabled printers"
+#~ msgstr "Imprimantes réseau"
+
+#~ msgctxt "@info:title"
+#~ msgid "Local printers"
+#~ msgstr "Imprimantes locales"
+
+#~ msgctxt "@info:backup_failed"
+#~ msgid "Tried to restore a Cura backup that does not match your current version."
+#~ msgstr "A essayé de restaurer une sauvegarde Cura qui ne correspond pas à votre version actuelle."
+
+#~ msgctxt "@title"
+#~ msgid "Machine Settings"
+#~ msgstr "Paramètres de la machine"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Settings"
+#~ msgstr "Paramètres de l'imprimante"
+
+#~ msgctxt "@option:check"
+#~ msgid "Origin at center"
+#~ msgstr "Origine au centre"
+
+#~ msgctxt "@option:check"
+#~ msgid "Heated bed"
+#~ msgstr "Plateau chauffant"
+
+#~ msgctxt "@label"
+#~ msgid "Printhead Settings"
+#~ msgstr "Paramètres de la tête d'impression"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distance entre la gauche de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distance entre le devant de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distance entre la droite de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distance entre le dos de la tête d'impression et le centre de la buse. Permet d'empêcher les collisions entre les impressions précédentes et la tête d'impression lors d'une impression « Un à la fois »."
+
+#~ msgctxt "@label"
+#~ msgid "Gantry height"
+#~ msgstr "Hauteur du portique"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
+#~ msgstr "La différence de hauteur entre la pointe de la buse et le système de portique (axes X et Y). Permet d'empêcher les collisions entre les impressions précédentes et le portique lors d'une impression « Un à la fois »."
+
+#~ msgctxt "@label"
+#~ msgid "Start G-code"
+#~ msgstr "G-Code de démarrage"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very start."
+#~ msgstr "Commandes G-Code à exécuter au tout début."
+
+#~ msgctxt "@label"
+#~ msgid "End G-code"
+#~ msgstr "G-Code de fin"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very end."
+#~ msgstr "Commandes G-Code à exécuter tout à la fin."
+
+#~ msgctxt "@label"
+#~ msgid "Nozzle Settings"
+#~ msgstr "Paramètres de la buse"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
+#~ msgstr "Le diamètre nominal de filament pris en charge par l'imprimante. Le diamètre exact sera remplacé par le matériau et / ou le profil."
+
+#~ msgctxt "@label"
+#~ msgid "Extruder Start G-code"
+#~ msgstr "Extrudeuse G-Code de démarrage"
+
+#~ msgctxt "@label"
+#~ msgid "Extruder End G-code"
+#~ msgstr "Extrudeuse G-Code de fin"
+
+#~ msgctxt "@label"
+#~ msgid "Changelog"
+#~ msgstr "Récapitulatif des changements"
+
+#~ msgctxt "@title:window"
+#~ msgid "User Agreement"
+#~ msgstr "Accord utilisateur"
+
+#~ msgctxt "@alabel"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Saisissez l'adresse IP ou le nom d'hôte de votre imprimante sur le réseau."
+
+#~ msgctxt "@info"
+#~ msgid "Please select a network connected printer to monitor."
+#~ msgstr "Veuillez sélectionner une imprimante à surveiller qui est connectée au réseau."
+
+#~ msgctxt "@info"
+#~ msgid "Please connect your Ultimaker printer to your local network."
+#~ msgstr "Veuillez connecter votre imprimante Ultimaker à votre réseau local."
+
+#~ msgctxt "@text:window"
+#~ msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
+#~ msgstr "Cura envoie des données anonymes à Ultimaker afin d'améliorer la qualité d'impression et l'expérience utilisateur. Voici un exemple de toutes les données envoyées."
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send this data"
+#~ msgstr "Je ne veux pas envoyer ces données"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending this data to Ultimaker and help us improve Cura"
+#~ msgstr "Permettre l'envoi de ces données à Ultimaker et nous aider à améliorer Cura"
+
+#~ msgctxt "@label"
+#~ msgid "No print selected"
+#~ msgstr "Aucune impression sélectionnée"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
+#~ msgstr "Par défaut, les pixels blancs représentent les points hauts sur la maille tandis que les pixels noirs représentent les points bas sur la maille. Modifiez cette option pour inverser le comportement de manière à ce que les pixels noirs représentent les points hauts sur la maille et les pixels blancs les points bas."
+
+#~ msgctxt "@title"
+#~ msgid "Select Printer Upgrades"
+#~ msgstr "Sélectionner les mises à niveau de l'imprimante"
+
+#~ msgctxt "@label"
+#~ msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
+#~ msgstr "Sélectionnez l'extrudeur à utiliser comme support. Cela créera des structures de support sous le modèle afin de l'empêcher de s'affaisser ou de s'imprimer dans les airs."
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
+#~ msgstr "Ce profil de qualité n'est pas disponible pour votre matériau et configuration des buses actuels. Veuillez modifier ces derniers pour activer ce profil de qualité."
+
+#~ msgctxt "@label shown when we load a Gcode file"
+#~ msgid "Print setup disabled. G code file can not be modified."
+#~ msgstr "Configuration d'impression désactivée. Le fichier G-Code ne peut pas être modifié."
+
+#~ msgctxt "@label"
+#~ msgid "See the material compatibility chart"
+#~ msgstr "Voir le tableau de compatibilité des matériaux"
+
+#~ msgctxt "@label"
+#~ msgid "View types"
+#~ msgstr "Types d'affichages"
+
+#~ msgctxt "@label"
+#~ msgid "Hi "
+#~ msgstr "Bonjour "
+
+#~ msgctxt "@text"
+#~ msgid ""
+#~ "- Send print jobs to Ultimaker printers outside your local network\n"
+#~ "- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
+#~ "- Get exclusive access to material profiles from leading brands"
+#~ msgstr ""
+#~ "- Envoyez des tâches d'impression à des imprimantes Ultimaker hors de votre réseau local\n"
+#~ "- Stockez vos paramètres Ultimaker Cura dans le cloud pour les utiliser où que vous soyez\n"
+#~ "- Obtenez un accès exclusif aux profils de matériaux des principales marques"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Unable to Slice"
+#~ msgstr "Impossible de découper"
+
+#~ msgctxt "@label"
+#~ msgid "Time specification"
+#~ msgstr "Spécification de durée"
+
+#~ msgctxt "@label"
+#~ msgid "Material specification"
+#~ msgstr "Spécification des matériaux"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Add a printer to Cura"
+#~ msgstr "Ajouter une imprimante à Cura"
+
+#~ msgctxt "@title:tab"
+#~ msgid ""
+#~ "Select the printer you want to use from the list below.\n"
+#~ "\n"
+#~ "If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
+#~ msgstr ""
+#~ "Sélectionnez l'imprimante que vous voulez utiliser dans la liste ci-dessous.\n"
+#~ "\n"
+#~ "Si votre imprimante n'est pas dans la liste, utilisez l'imprimante « Imprimante FFF personnalisée » de la catégorie « Personnalisé » et ajustez les paramètres pour qu'ils correspondent à votre imprimante dans le dialogue suivant."
+
+#~ msgctxt "@label"
+#~ msgid "Manufacturer"
+#~ msgstr "Fabricant"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name"
+#~ msgstr "Nom de l'imprimante"
+
+#~ msgctxt "@action:button"
+#~ msgid "Add Printer"
+#~ msgstr "Ajouter une imprimante"
#~ msgid "Modify G-Code"
#~ msgstr "Modifier le G-Code"
@@ -5328,62 +6474,6 @@ msgstr "X3GWriter"
#~ msgid "Click to check the material compatibility on Ultimaker.com."
#~ msgstr "Cliquez ici pour vérifier la compatibilité des matériaux sur Ultimaker.com."
-#~ msgctxt "description"
-#~ msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
-#~ msgstr "Permet de modifier les paramètres de la machine (tels que volume d'impression, taille de buse, etc.)"
-
-#~ msgctxt "name"
-#~ msgid "Machine Settings action"
-#~ msgstr "Action Paramètres de la machine"
-
-#~ msgctxt "description"
-#~ msgid "Find, manage and install new Cura packages."
-#~ msgstr "Rechercher, gérer et installer de nouveaux paquets Cura."
-
-#~ msgctxt "name"
-#~ msgid "Toolbox"
-#~ msgstr "Boîte à outils"
-
-#~ msgctxt "description"
-#~ msgid "Provides the X-Ray view."
-#~ msgstr "Permet la vue Rayon-X."
-
-#~ msgctxt "name"
-#~ msgid "X-Ray View"
-#~ msgstr "Vue Rayon-X"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading X3D files."
-#~ msgstr "Fournit la prise en charge de la lecture de fichiers X3D."
-
-#~ msgctxt "name"
-#~ msgid "X3D Reader"
-#~ msgstr "Lecteur X3D"
-
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a file."
-#~ msgstr "Enregistre le G-Code dans un fichier."
-
-#~ msgctxt "name"
-#~ msgid "G-code Writer"
-#~ msgstr "Générateur de G-Code"
-
-#~ msgctxt "description"
-#~ msgid "Checks models and print configuration for possible printing issues and give suggestions."
-#~ msgstr "Vérifie les modèles et la configuration de l'impression pour déceler d'éventuels problèmes d'impression et donne des suggestions."
-
-#~ msgctxt "name"
-#~ msgid "Model Checker"
-#~ msgstr "Contrôleur de modèle"
-
-#~ msgctxt "description"
-#~ msgid "Dump the contents of all settings to a HTML file."
-#~ msgstr "Exporter les contenus de tous les paramètres vers un fichier HTML."
-
-#~ msgctxt "name"
-#~ msgid "God Mode"
-#~ msgstr "Mode God"
-
#~ msgctxt "description"
#~ msgid "Shows changes since latest checked version."
#~ msgstr "Affiche les changements depuis la dernière version."
@@ -5392,14 +6482,6 @@ msgstr "X3GWriter"
#~ msgid "Changelog"
#~ msgstr "Récapitulatif des changements"
-#~ msgctxt "description"
-#~ msgid "Provides a machine actions for updating firmware."
-#~ msgstr "Fournit à une machine des actions permettant la mise à jour du firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Updater"
-#~ msgstr "Programme de mise à jour du firmware"
-
#~ msgctxt "description"
#~ msgid "Create a flattend quality changes profile."
#~ msgstr "Créer un profil de changements de qualité aplati."
@@ -5408,14 +6490,6 @@ msgstr "X3GWriter"
#~ msgid "Profile flatener"
#~ msgstr "Aplatisseur de profil"
-#~ msgctxt "description"
-#~ msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
-#~ msgstr "Accepte les G-Code et les envoie à une imprimante. Ce plugin peut aussi mettre à jour le firmware."
-
-#~ msgctxt "name"
-#~ msgid "USB printing"
-#~ msgstr "Impression par USB"
-
#~ msgctxt "description"
#~ msgid "Ask the user once if he/she agrees with our license."
#~ msgstr "Demander à l'utilisateur une fois s'il appose son accord à notre licence."
@@ -5424,278 +6498,6 @@ msgstr "X3GWriter"
#~ msgid "UserAgreement"
#~ msgstr "UserAgreement"
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a compressed archive."
-#~ msgstr "Enregistre le G-Code dans une archive compressée."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Writer"
-#~ msgstr "Générateur de G-Code compressé"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing Ultimaker Format Packages."
-#~ msgstr "Permet l'écriture de fichiers Ultimaker Format Package."
-
-#~ msgctxt "name"
-#~ msgid "UFP Writer"
-#~ msgstr "Générateur UFP"
-
-#~ msgctxt "description"
-#~ msgid "Provides a prepare stage in Cura."
-#~ msgstr "Fournit une étape de préparation dans Cura."
-
-#~ msgctxt "name"
-#~ msgid "Prepare Stage"
-#~ msgstr "Étape de préparation"
-
-#~ msgctxt "description"
-#~ msgid "Provides removable drive hotplugging and writing support."
-#~ msgstr "Permet le branchement hot-plug et l'écriture sur lecteur amovible."
-
-#~ msgctxt "name"
-#~ msgid "Removable Drive Output Device Plugin"
-#~ msgstr "Plugin de périphérique de sortie sur disque amovible"
-
-#~ msgctxt "description"
-#~ msgid "Manages network connections to Ultimaker 3 printers."
-#~ msgstr "Gère les connexions réseau vers les imprimantes Ultimaker 3."
-
-#~ msgctxt "name"
-#~ msgid "UM3 Network Connection"
-#~ msgstr "Connexion au réseau UM3"
-
-#~ msgctxt "description"
-#~ msgid "Provides a monitor stage in Cura."
-#~ msgstr "Fournit une étape de surveillance dans Cura."
-
-#~ msgctxt "name"
-#~ msgid "Monitor Stage"
-#~ msgstr "Étape de surveillance"
-
-#~ msgctxt "description"
-#~ msgid "Checks for firmware updates."
-#~ msgstr "Vérifie les mises à jour du firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Update Checker"
-#~ msgstr "Vérificateur des mises à jour du firmware"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Simulation view."
-#~ msgstr "Fournit la Vue simulation."
-
-#~ msgctxt "name"
-#~ msgid "Simulation View"
-#~ msgstr "Vue simulation"
-
-#~ msgctxt "description"
-#~ msgid "Reads g-code from a compressed archive."
-#~ msgstr "Lit le G-Code à partir d'une archive compressée."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Reader"
-#~ msgstr "Lecteur G-Code compressé"
-
-#~ msgctxt "description"
-#~ msgid "Extension that allows for user created scripts for post processing"
-#~ msgstr "Extension qui permet le post-traitement des scripts créés par l'utilisateur"
-
-#~ msgctxt "name"
-#~ msgid "Post Processing"
-#~ msgstr "Post-traitement"
-
-#~ msgctxt "description"
-#~ msgid "Creates an eraser mesh to block the printing of support in certain places"
-#~ msgstr "Crée un maillage effaceur pour bloquer l'impression du support en certains endroits"
-
-#~ msgctxt "name"
-#~ msgid "Support Eraser"
-#~ msgstr "Effaceur de support"
-
-#~ msgctxt "description"
-#~ msgid "Submits anonymous slice info. Can be disabled through preferences."
-#~ msgstr "Envoie des informations anonymes sur le découpage. Peut être désactivé dans les préférences."
-
-#~ msgctxt "name"
-#~ msgid "Slice info"
-#~ msgstr "Information sur le découpage"
-
-#~ msgctxt "description"
-#~ msgid "Provides capabilities to read and write XML-based material profiles."
-#~ msgstr "Offre la possibilité de lire et d'écrire des profils matériels basés sur XML."
-
-#~ msgctxt "name"
-#~ msgid "Material Profiles"
-#~ msgstr "Profils matériels"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from legacy Cura versions."
-#~ msgstr "Fournit la prise en charge de l'importation de profils à partir de versions Cura antérieures."
-
-#~ msgctxt "name"
-#~ msgid "Legacy Cura Profile Reader"
-#~ msgstr "Lecteur de profil Cura antérieur"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from g-code files."
-#~ msgstr "Fournit la prise en charge de l'importation de profils à partir de fichiers g-code."
-
-#~ msgctxt "name"
-#~ msgid "G-code Profile Reader"
-#~ msgstr "Lecteur de profil G-Code"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
-#~ msgstr "Configurations des mises à niveau de Cura 3.2 vers Cura 3.3."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.2 to 3.3"
-#~ msgstr "Mise à niveau de 3.2 vers 3.3"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
-#~ msgstr "Configurations des mises à niveau de Cura 3.3 vers Cura 3.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.3 to 3.4"
-#~ msgstr "Mise à niveau de 3.3 vers 3.4"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
-#~ msgstr "Configurations des mises à niveau de Cura 2.5 vers Cura 2.6."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.5 to 2.6"
-#~ msgstr "Mise à niveau de 2.5 vers 2.6"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
-#~ msgstr "Met à niveau les configurations, de Cura 2.7 vers Cura 3.0."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.7 to 3.0"
-#~ msgstr "Mise à niveau de version, de 2.7 vers 3.0"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
-#~ msgstr "Configurations des mises à niveau de Cura 3.4 vers Cura 3.5."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.4 to 3.5"
-#~ msgstr "Mise à niveau de 3.4 vers 3.5"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
-#~ msgstr "Met à niveau les configurations, de Cura 3.0 vers Cura 3.1."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.0 to 3.1"
-#~ msgstr "Mise à niveau de version, de 3.0 vers 3.1"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
-#~ msgstr "Configurations des mises à niveau de Cura 2.6 vers Cura 2.7."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.6 to 2.7"
-#~ msgstr "Mise à niveau de 2.6 vers 2.7"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
-#~ msgstr "Configurations des mises à niveau de Cura 2.1 vers Cura 2.2."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.1 to 2.2"
-#~ msgstr "Mise à niveau vers 2.1 vers 2.2"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
-#~ msgstr "Configurations des mises à niveau de Cura 2.2 vers Cura 2.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.2 to 2.4"
-#~ msgstr "Mise à niveau de 2.2 vers 2.4"
-
-#~ msgctxt "description"
-#~ msgid "Enables ability to generate printable geometry from 2D image files."
-#~ msgstr "Permet de générer une géométrie imprimable à partir de fichiers d'image 2D."
-
-#~ msgctxt "name"
-#~ msgid "Image Reader"
-#~ msgstr "Lecteur d'images"
-
-#~ msgctxt "description"
-#~ msgid "Provides the link to the CuraEngine slicing backend."
-#~ msgstr "Fournit le lien vers l'arrière du système de découpage CuraEngine."
-
-#~ msgctxt "name"
-#~ msgid "CuraEngine Backend"
-#~ msgstr "Système CuraEngine"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Per Model Settings."
-#~ msgstr "Fournit les paramètres par modèle."
-
-#~ msgctxt "name"
-#~ msgid "Per Model Settings Tool"
-#~ msgstr "Outil de paramètres par modèle"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading 3MF files."
-#~ msgstr "Fournit la prise en charge de la lecture de fichiers 3MF."
-
-#~ msgctxt "name"
-#~ msgid "3MF Reader"
-#~ msgstr "Lecteur 3MF"
-
-#~ msgctxt "description"
-#~ msgid "Provides a normal solid mesh view."
-#~ msgstr "Affiche une vue en maille solide normale."
-
-#~ msgctxt "name"
-#~ msgid "Solid View"
-#~ msgstr "Vue solide"
-
-#~ msgctxt "description"
-#~ msgid "Allows loading and displaying G-code files."
-#~ msgstr "Permet le chargement et l'affichage de fichiers G-Code."
-
-#~ msgctxt "name"
-#~ msgid "G-code Reader"
-#~ msgstr "Lecteur G-Code"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for exporting Cura profiles."
-#~ msgstr "Fournit la prise en charge de l'exportation de profils Cura."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Writer"
-#~ msgstr "Générateur de profil Cura"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing 3MF files."
-#~ msgstr "Permet l'écriture de fichiers 3MF."
-
-#~ msgctxt "name"
-#~ msgid "3MF Writer"
-#~ msgstr "Générateur 3MF"
-
-#~ msgctxt "description"
-#~ msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
-#~ msgstr "Fournit les actions de la machine pour les machines Ultimaker (telles que l'assistant de calibration du plateau, sélection des mises à niveau, etc.)"
-
-#~ msgctxt "name"
-#~ msgid "Ultimaker machine actions"
-#~ msgstr "Actions de la machine Ultimaker"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing Cura profiles."
-#~ msgstr "Fournit la prise en charge de l'importation de profils Cura."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Reader"
-#~ msgstr "Lecteur de profil Cura"
-
#~ msgctxt "@warning:status"
#~ msgid "Please generate G-code before saving."
#~ msgstr "Veuillez générer le G-Code avant d'enregistrer."
@@ -5736,14 +6538,6 @@ msgstr "X3GWriter"
#~ msgid "Upgrade Firmware"
#~ msgstr "Mise à niveau du firmware"
-#~ msgctxt "description"
-#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
-#~ msgstr "Permet aux fabricants de matériaux de créer de nouveaux matériaux et profils de qualité à l'aide d'une interface utilisateur ad hoc."
-
-#~ msgctxt "name"
-#~ msgid "Print Profile Assistant"
-#~ msgstr "Assistant de profil d'impression"
-
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Imprimer avec Doodle3D WiFi-Box"
diff --git a/resources/i18n/fr_FR/fdmextruder.def.json.po b/resources/i18n/fr_FR/fdmextruder.def.json.po
index d9f8b75097..59ade887b6 100644
--- a/resources/i18n/fr_FR/fdmextruder.def.json.po
+++ b/resources/i18n/fr_FR/fdmextruder.def.json.po
@@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: French\n"
"Language: fr_FR\n"
@@ -84,7 +84,7 @@ msgstr "Extrudeuse G-Code de démarrage"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
msgid "Start g-code to execute when switching to this extruder."
-msgstr ""
+msgstr "Démarrer le G-Code à exécuter lors du passage à cette extrudeuse."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -124,7 +124,7 @@ msgstr "Extrudeuse G-Code de fin"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
msgid "End g-code to execute when switching away from this extruder."
-msgstr ""
+msgstr "Fin du G-Code à exécuter lors de l'abandon de l'extrudeuse."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
diff --git a/resources/i18n/fr_FR/fdmprinter.def.json.po b/resources/i18n/fr_FR/fdmprinter.def.json.po
index caeafec806..9779482577 100644
--- a/resources/i18n/fr_FR/fdmprinter.def.json.po
+++ b/resources/i18n/fr_FR/fdmprinter.def.json.po
@@ -5,12 +5,12 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 15:00+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: French\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: French , French \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -215,6 +215,16 @@ msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
msgstr "Si la machine a un plateau chauffé présent."
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume label"
+msgid "Has Build Volume Temperature Stabilization"
+msgstr "Est dotée de la stabilisation de la température du volume d'impression"
+
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume description"
+msgid "Whether the machine is able to stabilize the build volume temperature."
+msgstr "Si la machine est capable de stabiliser la température du volume d'impression."
+
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
@@ -237,7 +247,7 @@ msgstr "Nombre de trains d'extrudeuse. Un train d'extrudeuse est la combinaison
#: fdmprinter.def.json
msgctxt "extruders_enabled_count label"
-msgid "Number of Extruders that are enabled"
+msgid "Number of Extruders That Are Enabled"
msgstr "Nombre d'extrudeuses activées"
#: fdmprinter.def.json
@@ -247,7 +257,7 @@ msgstr "Nombre de trains d'extrusion activés ; automatiquement défini dans le
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
-msgid "Outer nozzle diameter"
+msgid "Outer Nozzle Diameter"
msgstr "Diamètre extérieur de la buse"
#: fdmprinter.def.json
@@ -257,7 +267,7 @@ msgstr "Le diamètre extérieur de la pointe de la buse."
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
+msgid "Nozzle Length"
msgstr "Longueur de la buse"
#: fdmprinter.def.json
@@ -267,7 +277,7 @@ msgstr "La différence de hauteur entre la pointe de la buse et la partie la plu
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
+msgid "Nozzle Angle"
msgstr "Angle de la buse"
#: fdmprinter.def.json
@@ -277,7 +287,7 @@ msgstr "L'angle entre le plan horizontal et la partie conique juste au-dessus de
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length label"
-msgid "Heat zone length"
+msgid "Heat Zone Length"
msgstr "Longueur de la zone chauffée"
#: fdmprinter.def.json
@@ -307,7 +317,7 @@ msgstr "Contrôler ou non la température depuis Cura. Désactivez cette option
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed label"
-msgid "Heat up speed"
+msgid "Heat Up Speed"
msgstr "Vitesse de chauffage"
#: fdmprinter.def.json
@@ -317,7 +327,7 @@ msgstr "La vitesse (°C/s) à laquelle la buse chauffe, sur une moyenne de la pl
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed label"
-msgid "Cool down speed"
+msgid "Cool Down Speed"
msgstr "Vitesse de refroidissement"
#: fdmprinter.def.json
@@ -337,7 +347,7 @@ msgstr "La durée minimale pendant laquelle une extrudeuse doit être inactive a
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
+msgid "G-code Flavor"
msgstr "Parfum G-Code"
#: fdmprinter.def.json
@@ -402,7 +412,7 @@ msgstr "S'il faut utiliser les commandes de rétraction du firmware (G10 / G11
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
+msgid "Disallowed Areas"
msgstr "Zones interdites"
#: fdmprinter.def.json
@@ -422,7 +432,7 @@ msgstr "Une liste de polygones comportant les zones dans lesquelles le bec n'a p
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
+msgid "Machine Head Polygon"
msgstr "Polygone de la tête de machine"
#: fdmprinter.def.json
@@ -432,8 +442,8 @@ msgstr "Une silhouette 2D de la tête d'impression (sans les capuchons du ventil
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
-msgid "Machine head & Fan polygon"
-msgstr "Tête de la machine et polygone du ventilateur"
+msgid "Machine Head & Fan Polygon"
+msgstr "Polygone de la tête de la machine et du ventilateur"
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon description"
@@ -442,7 +452,7 @@ msgstr "Une silhouette 2D de la tête d'impression (avec les capuchons du ventil
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Hauteur du portique"
#: fdmprinter.def.json
@@ -472,7 +482,7 @@ msgstr "Le diamètre intérieur de la buse. Modifiez ce paramètre si vous utili
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label"
-msgid "Offset With Extruder"
+msgid "Offset with Extruder"
msgstr "Décalage avec extrudeuse"
#: fdmprinter.def.json
@@ -1020,6 +1030,17 @@ msgctxt "bottom_layers description"
msgid "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number."
msgstr "Le nombre de couches inférieures. Lorsqu'elle est calculée par l'épaisseur du dessous, cette valeur est arrondie à un nombre entier."
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers label"
+msgid "Initial Bottom Layers"
+msgstr "Couches inférieures initiales"
+
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers description"
+msgid "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number."
+msgstr "Le nombre de couches inférieures initiales à partir du haut du plateau. Lorsqu'elle est calculée par l'épaisseur du dessous, cette valeur est arrondie"
+" à un nombre entier."
+
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
@@ -1223,7 +1244,7 @@ msgstr "Imprimer les parties du modèle qui sont horizontalement plus fines que
#: fdmprinter.def.json
msgctxt "xy_offset label"
msgid "Horizontal Expansion"
-msgstr "Vitesse d’impression horizontale"
+msgstr "Expansion horizontale"
#: fdmprinter.def.json
msgctxt "xy_offset description"
@@ -1270,6 +1291,56 @@ msgctxt "z_seam_type option sharpest_corner"
msgid "Sharpest Corner"
msgstr "Angle le plus aigu"
+#: fdmprinter.def.json
+msgctxt "z_seam_position label"
+msgid "Z Seam Position"
+msgstr "Position de la jointure en Z"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position description"
+msgid "The position near where to start printing each part in a layer."
+msgstr "La position près de laquelle démarre l'impression de chaque partie dans une couche."
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backleft"
+msgid "Back Left"
+msgstr "Arrière gauche"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option back"
+msgid "Back"
+msgstr "Précédent"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backright"
+msgid "Back Right"
+msgstr "Arrière droit"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option right"
+msgid "Right"
+msgstr "Droite"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontright"
+msgid "Front Right"
+msgstr "Avant droit"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option front"
+msgid "Front"
+msgstr "Avant"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontleft"
+msgid "Front Left"
+msgstr "Avant gauche"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option left"
+msgid "Left"
+msgstr "Gauche"
+
#: fdmprinter.def.json
msgctxt "z_seam_x label"
msgid "Z Seam X"
@@ -1297,8 +1368,8 @@ msgstr "Préférence de jointure d'angle"
#: fdmprinter.def.json
msgctxt "z_seam_corner description"
-msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
-msgstr "Vérifie si les angles du contour du modèle influencent l'emplacement de la jointure. « Aucune » signifie que les angles n'ont aucune influence sur l'emplacement de la jointure. « Masquer jointure » génère généralement le positionnement de la jointure sur un angle intérieur. « Exposer jointure » génère généralement le positionnement de la jointure sur un angle extérieur. « Masquer ou exposer jointure » génère généralement le positionnement de la jointure sur un angle intérieur ou extérieur."
+msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner. Smart Hiding allows both inside and outside corners, but chooses inside corners more frequently, if appropriate."
+msgstr "Vérifie si les angles du contour du modèle influencent l'emplacement de la jointure. « Aucune » signifie que les angles n'ont aucune influence sur l'emplacement de la jointure. « Masquer la jointure » génère le positionnement de la jointure sur un angle intérieur. « Exposer la jointure » génère le positionnement de la jointure sur un angle extérieur. « Masquer ou exposer la jointure » génère le positionnement de la jointure sur un angle intérieur ou extérieur. « Jointure intelligente » autorise les angles intérieurs et extérieurs, mais choisit plus fréquemment les angles intérieurs, le cas échéant."
#: fdmprinter.def.json
msgctxt "z_seam_corner option z_seam_corner_none"
@@ -1320,6 +1391,11 @@ msgctxt "z_seam_corner option z_seam_corner_any"
msgid "Hide or Expose Seam"
msgstr "Masquer ou exposer jointure"
+#: fdmprinter.def.json
+msgctxt "z_seam_corner option z_seam_corner_weighted"
+msgid "Smart Hiding"
+msgstr "Masquage intelligent"
+
#: fdmprinter.def.json
msgctxt "z_seam_relative label"
msgid "Z Seam Relative"
@@ -1332,13 +1408,13 @@ msgstr "Si cette option est activée, les coordonnées de la jointure z sont rel
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic label"
-msgid "Ignore Small Z Gaps"
-msgstr "Ignorer les petits trous en Z"
+msgid "No Skin in Z Gaps"
+msgstr "Aucune couche dans les trous en Z"
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic description"
-msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
-msgstr "Quand le modèle présente de petits trous verticaux, environ 5 % de temps de calcul supplémentaire peut être alloué à la génération de couches du dessus et du dessous dans ces espaces étroits. Dans ce cas, désactivez ce paramètre."
+msgid "When the model has small vertical gaps of only a few layers, there should normally be skin around those layers in the narrow space. Enable this setting to not generate skin if the vertical gap is very small. This improves printing time and slicing time, but technically leaves infill exposed to the air."
+msgstr "Lorsque le modèle comporte de petits trous verticaux de quelques couches seulement, il doit normalement y avoir une couche autour de celles-ci dans l'espace étroit. Activez ce paramètre pour ne pas générer de couche si le trou vertical est très petit. Cela améliore le temps d'impression et le temps de découpage, mais laisse techniquement le remplissage exposé à l'air."
#: fdmprinter.def.json
msgctxt "skin_outline_count label"
@@ -1357,8 +1433,8 @@ msgstr "Activer l'étirage"
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
-msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
-msgstr "Aller au-dessus de la surface supérieure une fois supplémentaire, mais sans extruder de matériau. Cela signifie de faire fondre le plastique en haut un peu plus, pour créer une surface lisse."
+msgid "Go over the top surface one additional time, but this time extruding very little material. This is meant to melt the plastic on top further, creating a smoother surface. The pressure in the nozzle chamber is kept high so that the creases in the surface are filled with material."
+msgstr "Allez au-dessus de la surface une fois supplémentaire, mais en extrudant très peu de matériau. Cela signifie de faire fondre le plastique en haut un peu plus, pour créer une surface lisse. La pression dans la chambre de la buse est maintenue élevée afin que les plis de la surface soient remplis de matériau."
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
@@ -1450,6 +1526,26 @@ msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
msgstr "Le changement instantané maximal de vitesse lors de l'étirage."
+#: fdmprinter.def.json
+msgctxt "skin_overlap label"
+msgid "Skin Overlap Percentage"
+msgstr "Pourcentage de chevauchement de la couche extérieure"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Ajuster le degré de chevauchement entre les parois et les (extrémités des) lignes centrales de la couche extérieure, en pourcentage de la largeur des lignes de la couche extérieure et de la paroi intérieure. Un chevauchement léger permet de relier fermement les parois à la couche extérieure. Notez que, si la largeur de la couche extérieure est égale à celle de la ligne de la paroi, un pourcentage supérieur à 50 % peut déjà faire dépasser la couche extérieure de la paroi, car dans ce cas la position de la buse de l'extrudeuse peut déjà atteindre le milieu de la paroi."
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm label"
+msgid "Skin Overlap"
+msgstr "Chevauchement de la couche extérieure"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Ajuster le degré de chevauchement entre les parois et les (extrémités des) lignes centrales de la couche extérieure. Un chevauchement léger permet de relier fermement les parois à la couche extérieure. Notez que, si la largeur de la couche extérieure est égale à celle de la ligne de la paroi, une valeur supérieure à la moitié de la largeur de la paroi peut déjà faire dépasser la couche extérieure de la paroi, car dans ce cas la position de la buse de l'extrudeuse peut déjà atteindre le milieu de la paroi."
+
#: fdmprinter.def.json
msgctxt "infill label"
msgid "Infill"
@@ -1615,6 +1711,16 @@ msgctxt "infill_offset_y description"
msgid "The infill pattern is moved this distance along the Y axis."
msgstr "Le motif de remplissage est décalé de cette distance sur l'axe Y."
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location label"
+msgid "Randomize Infill Start"
+msgstr "Randomiser le démarrage du remplissage"
+
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location description"
+msgid "Randomize which infill line is printed first. This prevents one segment becoming the strongest, but it does so at the cost of an additional travel move."
+msgstr "Randomisez la ligne de remplissage qui est imprimée en premier. Cela empêche un segment de devenir plus fort, mais cela se fait au prix d'un déplacement supplémentaire."
+
#: fdmprinter.def.json
msgctxt "infill_multiplier label"
msgid "Infill Line Multiplier"
@@ -1669,26 +1775,6 @@ msgctxt "infill_overlap_mm description"
msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
msgstr "Le degré de chevauchement entre le remplissage et les parois. Un léger chevauchement permet de lier fermement les parois au remplissage."
-#: fdmprinter.def.json
-msgctxt "skin_overlap label"
-msgid "Skin Overlap Percentage"
-msgstr "Pourcentage de chevauchement de la couche extérieure"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm label"
-msgid "Skin Overlap"
-msgstr "Chevauchement de la couche extérieure"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "infill_wipe_dist label"
msgid "Infill Wipe Distance"
@@ -1869,6 +1955,16 @@ msgctxt "default_material_print_temperature description"
msgid "The default temperature used for printing. This should be the \"base\" temperature of a material. All other print temperatures should use offsets based on this value"
msgstr "La température par défaut utilisée pour l'impression. Il doit s'agir de la température de « base » d'un matériau. Toutes les autres températures d'impression doivent utiliser des décalages basés sur cette valeur"
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature label"
+msgid "Build Volume Temperature"
+msgstr "Température du volume d'impression"
+
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature description"
+msgid "The temperature of the environment to print in. If this is 0, the build volume temperature will not be adjusted."
+msgstr "La température de l'environnement d'impression. Si cette valeur est 0, la température du volume d'impression ne sera pas ajustée."
+
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
msgid "Printing Temperature"
@@ -1979,6 +2075,86 @@ msgctxt "material_shrinkage_percentage description"
msgid "Shrinkage ratio in percentage."
msgstr "Taux de contraction en pourcentage."
+#: fdmprinter.def.json
+msgctxt "material_crystallinity label"
+msgid "Crystalline Material"
+msgstr "Matériau cristallin"
+
+#: fdmprinter.def.json
+msgctxt "material_crystallinity description"
+msgid "Is this material the type that breaks off cleanly when heated (crystalline), or is it the type that produces long intertwined polymer chains (non-crystalline)?"
+msgstr "Ce matériau se casse-t-il proprement lorsqu'il est chauffé (cristallin) ou est-ce le type qui produit de longues chaînes polymères entrelacées (non cristallines) ?"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position label"
+msgid "Anti-ooze Retracted Position"
+msgstr "Position anti-suintage rétractée"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position description"
+msgid "How far the material needs to be retracted before it stops oozing."
+msgstr "Jusqu'où le matériau doit être rétracté avant qu'il cesse de suinter."
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed label"
+msgid "Anti-ooze Retraction Speed"
+msgstr "Vitesse de rétraction de l'anti-suintage"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed description"
+msgid "How fast the material needs to be retracted during a filament switch to prevent oozing."
+msgstr "À quelle vitesse le matériau doit-il être rétracté lors d'un changement de filament pour empêcher le suintage."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position label"
+msgid "Break Preparation Retracted Position"
+msgstr "Préparation de rupture Position rétractée"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position description"
+msgid "How far the filament can be stretched before it breaks, while heated."
+msgstr "Jusqu'où le filament peut être étiré avant qu'il ne se casse, pendant qu'il est chauffé."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed label"
+msgid "Break Preparation Retraction Speed"
+msgstr "Vitesse de rétraction de préparation de rupture"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed description"
+msgid "How fast the filament needs to be retracted just before breaking it off in a retraction."
+msgstr "La vitesse à laquelle le filament doit être rétracté juste avant de le briser dans une rétraction."
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position label"
+msgid "Break Retracted Position"
+msgstr "Position rétractée de rupture"
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position description"
+msgid "How far to retract the filament in order to break it cleanly."
+msgstr "Jusqu'où rétracter le filament afin de le casser proprement."
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed label"
+msgid "Break Retraction Speed"
+msgstr "Vitesse de rétraction de rupture"
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed description"
+msgid "The speed at which to retract the filament in order to break it cleanly."
+msgstr "La vitesse à laquelle rétracter le filament afin de le rompre proprement."
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature label"
+msgid "Break Temperature"
+msgstr "Température de rupture"
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature description"
+msgid "The temperature at which the filament is broken for a clean break."
+msgstr "La température à laquelle le filament est cassé pour une rupture propre."
+
#: fdmprinter.def.json
msgctxt "material_flow label"
msgid "Flow"
@@ -1989,6 +2165,126 @@ msgctxt "material_flow description"
msgid "Flow compensation: the amount of material extruded is multiplied by this value."
msgstr "Compensation du débit : la quantité de matériau extrudée est multipliée par cette valeur."
+#: fdmprinter.def.json
+msgctxt "wall_material_flow label"
+msgid "Wall Flow"
+msgstr "Débit de paroi"
+
+#: fdmprinter.def.json
+msgctxt "wall_material_flow description"
+msgid "Flow compensation on wall lines."
+msgstr "Compensation de débit sur les lignes de la paroi."
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow label"
+msgid "Outer Wall Flow"
+msgstr "Débit de paroi externe"
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow description"
+msgid "Flow compensation on the outermost wall line."
+msgstr "Compensation de débit sur la ligne de la paroi la plus à l'extérieur."
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow label"
+msgid "Inner Wall(s) Flow"
+msgstr "Débit de paroi(s) interne(s)"
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow description"
+msgid "Flow compensation on wall lines for all wall lines except the outermost one."
+msgstr "Compensation de débit sur les lignes de la paroi pour toutes les lignes de paroi, à l'exception de la ligne la plus externe."
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow label"
+msgid "Top/Bottom Flow"
+msgstr "Débit du dessus/dessous"
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow description"
+msgid "Flow compensation on top/bottom lines."
+msgstr "Compensation de débit sur les lignes du dessus/dessous."
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow label"
+msgid "Top Surface Skin Flow"
+msgstr "Débit de la surface du dessus"
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow description"
+msgid "Flow compensation on lines of the areas at the top of the print."
+msgstr "Compensation de débit sur les lignes des zones en haut de l'impression."
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow label"
+msgid "Infill Flow"
+msgstr "Débit de remplissage"
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow description"
+msgid "Flow compensation on infill lines."
+msgstr "Compensation de débit sur les lignes de remplissage."
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow label"
+msgid "Skirt/Brim Flow"
+msgstr "Débit de la jupe/bordure"
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow description"
+msgid "Flow compensation on skirt or brim lines."
+msgstr "Compensation de débit sur les lignes de jupe ou bordure."
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow label"
+msgid "Support Flow"
+msgstr "Débit du support"
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow description"
+msgid "Flow compensation on support structure lines."
+msgstr "Compensation de débit sur les lignes de support."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow label"
+msgid "Support Interface Flow"
+msgstr "Débit de l'interface de support"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow description"
+msgid "Flow compensation on lines of support roof or floor."
+msgstr "Compensation de débit sur les lignes de plafond ou de bas de support."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow label"
+msgid "Support Roof Flow"
+msgstr "Débit du plafond de support"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow description"
+msgid "Flow compensation on support roof lines."
+msgstr "Compensation de débit sur les lignes du plafond de support."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow label"
+msgid "Support Floor Flow"
+msgstr "Débit du bas de support"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow description"
+msgid "Flow compensation on support floor lines."
+msgstr "Compensation de débit sur les lignes de bas de support."
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow label"
+msgid "Prime Tower Flow"
+msgstr "Débit de la tour primaire"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow description"
+msgid "Flow compensation on prime tower lines."
+msgstr "Compensation de débit sur les lignes de la tour primaire."
+
#: fdmprinter.def.json
msgctxt "material_flow_layer_0 label"
msgid "Initial Layer Flow"
@@ -2106,8 +2402,8 @@ msgstr "Limiter les rétractations du support"
#: fdmprinter.def.json
msgctxt "limit_support_retractions description"
-msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
-msgstr "Omettre la rétraction lors du passage entre supports en ligne droite. L'activation de ce paramètre permet de gagner du temps lors de l'impression, mais peut conduire à un cordage excessif à l'intérieur de la structure de support."
+msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure."
+msgstr "Omettre la rétraction lors du passage entre supports en ligne droite. L'activation de ce paramètre permet de gagner du temps lors de l'impression, mais peut conduire à un stringing excessif à l'intérieur de la structure de support."
#: fdmprinter.def.json
msgctxt "material_standby_temperature label"
@@ -2127,7 +2423,7 @@ msgstr "Distance de rétraction de changement de buse"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
msgid "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr ""
+msgstr "Degré de rétraction lors de la commutation d'extrudeuses. Une valeur de 0 signifie qu'il n'y aura aucune rétraction. En général, cette valeur doit être équivalente à la longueur de la zone de chauffe."
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_speeds label"
@@ -2159,6 +2455,16 @@ msgctxt "switch_extruder_prime_speed description"
msgid "The speed at which the filament is pushed back after a nozzle switch retraction."
msgstr "La vitesse à laquelle le filament est poussé vers l'arrière après une rétraction de changement de buse."
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount label"
+msgid "Nozzle Switch Extra Prime Amount"
+msgstr "Montant de l'amorce supplémentaire lors d'un changement de buse"
+
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount description"
+msgid "Extra material to prime after nozzle switching."
+msgstr "Matériel supplémentaire à amorcer après le changement de buse."
+
#: fdmprinter.def.json
msgctxt "speed label"
msgid "Speed"
@@ -2350,14 +2656,14 @@ msgid "The speed at which the skirt and brim are printed. Normally this is done
msgstr "La vitesse à laquelle la jupe et la bordure sont imprimées. Normalement, cette vitesse est celle de la couche initiale, mais il est parfois nécessaire d’imprimer la jupe ou la bordure à une vitesse différente."
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override label"
-msgid "Maximum Z Speed"
-msgstr "Vitesse Z maximale"
+msgctxt "speed_z_hop label"
+msgid "Z Hop Speed"
+msgstr "Vitesse du décalage en Z"
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override description"
-msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
-msgstr "La vitesse maximale à laquelle le plateau se déplace. Définir cette valeur sur zéro impose à l'impression d'utiliser les valeurs par défaut du firmware pour la vitesse z maximale."
+msgctxt "speed_z_hop description"
+msgid "The speed at which the vertical Z movement is made for Z Hops. This is typically lower than the print speed since the build plate or machine's gantry is harder to move."
+msgstr "La vitesse à laquelle le mouvement vertical en Z est effectué pour des décalages en Z. Cette vitesse est généralement inférieure à la vitesse d'impression car le plateau ou le portique de la machine est plus difficile à déplacer."
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers label"
@@ -2787,7 +3093,7 @@ msgstr "Mode de détours"
#: fdmprinter.def.json
msgctxt "retraction_combing description"
msgid "Combing keeps the nozzle within already printed areas when traveling. This results in slightly longer travel moves but reduces the need for retractions. If combing is off, the material will retract and the nozzle moves in a straight line to the next point. It is also possible to avoid combing over top/bottom skin areas or to only comb within the infill."
-msgstr ""
+msgstr "Les détours maintiennent la buse dans les zones déjà imprimées lors des déplacements. Cela résulte en des déplacements légèrement plus longs mais réduit le recours aux rétractions. Si les détours sont désactivés, le matériau se rétractera et la buse se déplacera en ligne droite jusqu'au point suivant. Il est également possible d'éviter les détours sur les zones de la couche du dessus / dessous ou d'effectuer les détours uniquement dans le remplissage."
#: fdmprinter.def.json
msgctxt "retraction_combing option off"
@@ -2859,16 +3165,6 @@ msgctxt "travel_avoid_distance description"
msgid "The distance between the nozzle and already printed parts when avoiding during travel moves."
msgstr "La distance entre la buse et les pièces déjà imprimées lors du contournement pendant les déplacements."
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position label"
-msgid "Start Layers with the Same Part"
-msgstr "Démarrer les couches avec la même partie"
-
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position description"
-msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
-msgstr "Dans chaque couche, démarre l'impression de l'objet à proximité du même point, de manière à ce que nous ne commencions pas une nouvelle couche en imprimant la pièce avec laquelle la couche précédente s'est terminée. Cela renforce les porte-à-faux et les petites pièces, mais augmente le temps d'impression."
-
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
@@ -2929,6 +3225,16 @@ msgctxt "retraction_hop_after_extruder_switch description"
msgid "After the machine switched from one extruder to the other, the build plate is lowered to create clearance between the nozzle and the print. This prevents the nozzle from leaving oozed material on the outside of a print."
msgstr "Une fois que la machine est passée d'une extrudeuse à l'autre, le plateau s'abaisse pour créer un dégagement entre la buse et l'impression. Cela évite que la buse ne ressorte avec du matériau suintant sur l'extérieur d'une impression."
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height label"
+msgid "Z Hop After Extruder Switch Height"
+msgstr "Décalage en Z après changement de hauteur d'extrudeuse"
+
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height description"
+msgid "The height difference when performing a Z Hop after extruder switch."
+msgstr "La différence de hauteur lors de la réalisation d'un décalage en Z après changement d'extrudeuse."
+
#: fdmprinter.def.json
msgctxt "cooling label"
msgid "Cooling"
@@ -3199,6 +3505,11 @@ msgctxt "support_pattern option cross"
msgid "Cross"
msgstr "Entrecroisé"
+#: fdmprinter.def.json
+msgctxt "support_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Gyroïde"
+
#: fdmprinter.def.json
msgctxt "support_wall_count label"
msgid "Support Wall Line Count"
@@ -3260,14 +3571,14 @@ msgid "Distance between the printed initial layer support structure lines. This
msgstr "Distance entre les lignes de la structure de support de la couche initiale imprimée. Ce paramètre est calculé en fonction de la densité du support."
#: fdmprinter.def.json
-msgctxt "support_infill_angle label"
-msgid "Support Infill Line Direction"
+msgctxt "support_infill_angles label"
+msgid "Support Infill Line Directions"
msgstr "Direction de ligne de remplissage du support"
#: fdmprinter.def.json
-msgctxt "support_infill_angle description"
-msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
-msgstr "Orientation du motif de remplissage pour les supports. Le motif de remplissage du support pivote dans le plan horizontal."
+msgctxt "support_infill_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees."
+msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser. Les éléments de la liste sont utilisés de manière séquentielle à mesure de l'avancement des couches. La liste reprend depuis le début lorsque la fin est atteinte. Les éléments de la liste sont séparés par des virgules et la liste entière est encadrée entre crochets. La valeur par défaut est une liste vide, ce qui signifie que l'angle par défaut est utilisé (0 degré)."
#: fdmprinter.def.json
msgctxt "support_brim_enable label"
@@ -3396,8 +3707,8 @@ msgstr "Distance de jointement des supports"
#: fdmprinter.def.json
msgctxt "support_join_distance description"
-msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
-msgstr "La distance maximale entre les supports dans les directions X/Y. Lorsque des supports séparés sont plus rapprochés que cette valeur, ils fusionnent."
+msgid "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one."
+msgstr "La distance maximale entre les supports dans les directions X/Y. Lorsque des modèle séparés sont plus rapprochés que cette valeur, ils fusionnent."
#: fdmprinter.def.json
msgctxt "support_offset label"
@@ -3442,12 +3753,12 @@ msgstr "La hauteur de remplissage de support d'une densité donnée avant de pas
#: fdmprinter.def.json
msgctxt "minimum_support_area label"
msgid "Minimum Support Area"
-msgstr ""
+msgstr "Surface minimale de support"
#: fdmprinter.def.json
msgctxt "minimum_support_area description"
msgid "Minimum area size for support polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgstr "Taille minimale de la surface des polygones de support : les polygones dont la surface est inférieure à cette valeur ne seront pas générés."
#: fdmprinter.def.json
msgctxt "support_interface_enable label"
@@ -3677,62 +3988,94 @@ msgstr "Zig Zag"
#: fdmprinter.def.json
msgctxt "minimum_interface_area label"
msgid "Minimum Support Interface Area"
-msgstr ""
+msgstr "Surface minimale de l'interface de support"
#: fdmprinter.def.json
msgctxt "minimum_interface_area description"
-msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Taille minimale de la surface des polygones d'interface de support. Les polygones dont la surface est inférieure à cette valeur ne seront pas imprimés"
+" comme support normal."
#: fdmprinter.def.json
msgctxt "minimum_roof_area label"
msgid "Minimum Support Roof Area"
-msgstr ""
+msgstr "Surface minimale du plafond de support"
#: fdmprinter.def.json
msgctxt "minimum_roof_area description"
-msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Taille minimale de la surface des plafonds du support. Les polygones dont la surface est inférieure à cette valeur ne seront pas imprimés comme support"
+" normal."
#: fdmprinter.def.json
msgctxt "minimum_bottom_area label"
msgid "Minimum Support Floor Area"
-msgstr ""
+msgstr "Surface minimale du bas de support"
#: fdmprinter.def.json
msgctxt "minimum_bottom_area description"
-msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Taille minimale de la surface des bas du support. Les polygones dont la surface est inférieure à cette valeur ne seront pas imprimés comme support normal."
#: fdmprinter.def.json
msgctxt "support_interface_offset label"
msgid "Support Interface Horizontal Expansion"
-msgstr ""
+msgstr "Expansion horizontale de l'interface de support"
#: fdmprinter.def.json
msgctxt "support_interface_offset description"
msgid "Amount of offset applied to the support interface polygons."
-msgstr ""
+msgstr "Quantité de décalage appliquée aux polygones de l'interface de support."
#: fdmprinter.def.json
msgctxt "support_roof_offset label"
msgid "Support Roof Horizontal Expansion"
-msgstr ""
+msgstr "Expansion horizontale du plafond de support"
#: fdmprinter.def.json
msgctxt "support_roof_offset description"
msgid "Amount of offset applied to the roofs of the support."
-msgstr ""
+msgstr "Quantité de décalage appliqué aux plafonds du support."
#: fdmprinter.def.json
msgctxt "support_bottom_offset label"
msgid "Support Floor Horizontal Expansion"
-msgstr ""
+msgstr "Expansion horizontale du bas de support"
#: fdmprinter.def.json
msgctxt "support_bottom_offset description"
msgid "Amount of offset applied to the floors of the support."
-msgstr ""
+msgstr "Quantité de décalage appliqué aux bas du support."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles label"
+msgid "Support Interface Line Directions"
+msgstr "Direction de ligne d'interface du support"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser. Les éléments de la liste sont utilisés de manière séquentielle à mesure de l'avancement des couches. La liste reprend depuis le début lorsque la fin est atteinte. Les éléments de la liste sont séparés par des virgules et la liste entière est encadrée entre crochets. La valeur par défaut est une liste vide, ce qui signifie que les angles par défaut sont utilisés (alternative entre 45 et 135 degrés si les interfaces sont assez épaisses ou 90 degrés)."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles label"
+msgid "Support Roof Line Directions"
+msgstr "Direction de la ligne de plafond de support"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser. Les éléments de la liste sont utilisés de manière séquentielle à mesure de l'avancement des couches. La liste reprend depuis le début lorsque la fin est atteinte. Les éléments de la liste sont séparés par des virgules et la liste entière est encadrée entre crochets. La valeur par défaut est une liste vide, ce qui signifie que les angles par défaut sont utilisés (alternative entre 45 et 135 degrés si les interfaces sont assez épaisses ou 90 degrés)."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles label"
+msgid "Support Floor Line Directions"
+msgstr "Direction de la ligne de bas de support"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser. Les éléments de la liste sont utilisés de manière séquentielle à mesure de l'avancement des couches. La liste reprend depuis le début lorsque la fin est atteinte. Les éléments de la liste sont séparés par des virgules et la liste entière est encadrée entre crochets. La valeur par défaut est une liste vide, ce qui signifie que les angles par défaut sont utilisés (alternative entre 45 et 135 degrés si les interfaces sont assez épaisses ou 90 degrés)."
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
@@ -3775,14 +4118,14 @@ msgid "The diameter of a special tower."
msgstr "Le diamètre d’une tour spéciale."
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter label"
-msgid "Minimum Diameter"
-msgstr "Diamètre minimal"
+msgctxt "support_tower_maximum_supported_diameter label"
+msgid "Maximum Tower-Supported Diameter"
+msgstr "Diamètre maximal supporté par la tour"
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter description"
-msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
-msgstr "Le diamètre minimal sur les axes X/Y d’une petite zone qui doit être soutenue par une tour de soutien spéciale."
+msgctxt "support_tower_maximum_supported_diameter description"
+msgid "Maximum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+msgstr "Le diamètre maximal sur les axes X/Y d’une petite zone qui doit être soutenue par une tour de soutien spéciale."
#: fdmprinter.def.json
msgctxt "support_tower_roof_angle label"
@@ -4278,16 +4621,6 @@ msgctxt "prime_tower_enable description"
msgid "Print a tower next to the print which serves to prime the material after each nozzle switch."
msgstr "Imprimer une tour à côté de l'impression qui sert à amorcer le matériau après chaque changement de buse."
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular label"
-msgid "Circular Prime Tower"
-msgstr "Tour primaire circulaire"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular description"
-msgid "Make the prime tower as a circular shape."
-msgstr "Réaliser la tour primaire en forme circulaire."
-
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
@@ -4328,16 +4661,6 @@ msgctxt "prime_tower_position_y description"
msgid "The y coordinate of the position of the prime tower."
msgstr "Les coordonnées Y de la position de la tour primaire."
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow label"
-msgid "Prime Tower Flow"
-msgstr "Débit de la tour primaire"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow description"
-msgid "Flow compensation: the amount of material extruded is multiplied by this value."
-msgstr "Compensation du débit : la quantité de matériau extrudée est multipliée par cette valeur."
-
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
@@ -4348,6 +4671,16 @@ msgctxt "prime_tower_wipe_enabled description"
msgid "After printing the prime tower with one nozzle, wipe the oozed material from the other nozzle off on the prime tower."
msgstr "Après l'impression de la tour primaire à l'aide d'une buse, nettoyer le matériau qui suinte de l'autre buse sur la tour primaire."
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable label"
+msgid "Prime Tower Brim"
+msgstr "Bordure de la tour primaire"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable description"
+msgid "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type."
+msgstr "Les tours primaires peuvent avoir besoin de l'adhérence supplémentaire d'une bordure, même si le modèle n'en a pas besoin. Ne peut actuellement pas être utilisé avec le type d'adhérence « Raft » (radeau)."
+
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
msgid "Enable Ooze Shield"
@@ -4468,6 +4801,36 @@ msgctxt "remove_empty_first_layers description"
msgid "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle."
msgstr "Supprimer les couches vides sous la première couche imprimée si elles sont présentes. Le fait de désactiver ce paramètre peut entraîner l'apparition de premières couches vides si le paramètre Tolérance à la découpe est défini sur Exclusif ou Milieu."
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Résolution maximum"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "Taille minimum d'un segment de ligne après découpage. Si vous augmentez cette valeur, la maille aura une résolution plus faible. Cela peut permettre à l'imprimante de suivre la vitesse à laquelle elle doit traiter le G-Code et augmentera la vitesse de découpe en enlevant des détails de la maille que l'imprimante ne peut pas traiter de toute manière."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution label"
+msgid "Maximum Travel Resolution"
+msgstr "Résolution de déplacement maximum"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution description"
+msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
+msgstr "Taille minimale d'un segment de ligne de déplacement après la découpe. Si vous augmentez cette valeur, les mouvements de déplacement auront des coins moins lisses. Cela peut permettre à l'imprimante de suivre la vitesse à laquelle elle doit traiter le G-Code, mais cela peut réduire la précision de l'évitement du modèle."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation label"
+msgid "Maximum Deviation"
+msgstr "Écart maximum"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation description"
+msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true."
+msgstr "L'écart maximum autorisé lors de la réduction de la résolution pour le paramètre Résolution maximum. Si vous augmentez cette valeur, l'impression sera moins précise, mais le G-Code sera plus petit. L'écart maximum est une limite pour la résolution maximum. Donc si les deux entrent en conflit, l'Écart maximum restera valable."
+
#: fdmprinter.def.json
msgctxt "blackmagic label"
msgid "Special Modes"
@@ -4630,8 +4993,8 @@ msgstr "Lisser les contours spiralisés"
#: fdmprinter.def.json
msgctxt "smooth_spiralized_contours description"
-msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
-msgstr "Lisser les contours spiralisés pour réduire la visibilité de la jointure en Z (la jointure en Z doit être à peine visible sur l'impression mais sera toujours visible dans la vue en couches). Veuillez remarquer que le lissage aura tendance à estomper les détails fins de la surface."
+msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+msgstr "Lisser les contours spiralisés pour réduire la visibilité de la jointure en Z (la jointure en Z doit être à peine visible sur l'impression mais sera toujours visible dans la vue en couches). Veuillez remarquer que le lissage aura tendance à estomper les détails très fins de la surface."
#: fdmprinter.def.json
msgctxt "relative_extrusion label"
@@ -4843,26 +5206,6 @@ msgctxt "minimum_polygon_circumference description"
msgid "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details."
msgstr "Les polygones en couches tranchées dont la circonférence est inférieure à cette valeur seront filtrés. Des valeurs élevées permettent d'obtenir un maillage de meilleure résolution mais augmentent le temps de découpe. Cette option est principalement destinée aux imprimantes SLA haute résolution et aux modèles 3D de très petite taille avec beaucoup de détails."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Résolution maximum"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "Taille minimum d'un segment de ligne après découpage. Si vous augmentez cette valeur, la maille aura une résolution plus faible. Cela peut permettre à l'imprimante de suivre la vitesse à laquelle elle doit traiter le G-Code et augmentera la vitesse de découpe en enlevant des détails de la maille que l'imprimante ne peut pas traiter de toute manière."
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution label"
-msgid "Maximum Travel Resolution"
-msgstr "Résolution de déplacement maximum"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution description"
-msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
-msgstr "Taille minimale d'un segment de ligne de déplacement après la découpe. Si vous augmentez cette valeur, les mouvements de déplacement auront des coins moins lisses. Cela peut permettre à l'imprimante de suivre la vitesse à laquelle elle doit traiter le G-Code, mais cela peut réduire la précision de l'évitement du modèle."
-
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5003,16 +5346,6 @@ msgctxt "coasting_speed description"
msgid "The speed by which to move during coasting, relative to the speed of the extrusion path. A value slightly under 100% is advised, since during the coasting move the pressure in the bowden tube drops."
msgstr "Vitesse de déplacement pendant une roue libre, par rapport à la vitesse de déplacement pendant l'extrusion. Une valeur légèrement inférieure à 100 % est conseillée car, lors du mouvement en roue libre, la pression dans le tube bowden chute."
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation label"
-msgid "Alternate Skin Rotation"
-msgstr "Alterner la rotation dans les couches extérieures"
-
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation description"
-msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
-msgstr "Alterne le sens d'impression des couches du dessus/dessous. Elles sont généralement imprimées uniquement en diagonale. Ce paramètre ajoute les sens X uniquement et Y uniquement."
-
#: fdmprinter.def.json
msgctxt "cross_infill_pocket_size label"
msgid "Cross 3D Pocket Size"
@@ -5120,8 +5453,8 @@ msgstr "Activer les supports coniques"
#: fdmprinter.def.json
msgctxt "support_conical_enabled description"
-msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
-msgstr "Fonctionnalité expérimentale : rendre les aires de support plus petites en bas qu'au niveau du porte-à-faux à supporter."
+msgid "Make support areas smaller at the bottom than at the overhang."
+msgstr "Rendre les aires de support plus petites en bas qu'au niveau du porte-à-faux à supporter."
#: fdmprinter.def.json
msgctxt "support_conical_angle label"
@@ -5185,23 +5518,24 @@ msgstr "Distance moyenne entre les points ajoutés aléatoirement sur chaque seg
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
-msgid "Flow rate compensation max extrusion offset"
+msgid "Flow Rate Compensation Max Extrusion Offset"
msgstr "Décalage d'extrusion max. pour compensation du débit"
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
-msgid "The maximum distance in mm to compensate."
-msgstr "Distance de compensation maximum en mm."
+msgid "The maximum distance in mm to move the filament to compensate for changes in flow rate."
+msgstr "La distance maximale en mm pour déplacer le filament afin de compenser les variations du débit."
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor label"
-msgid "Flow rate compensation factor"
+msgid "Flow Rate Compensation Factor"
msgstr "Facteur de compensation du débit"
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor description"
-msgid "The multiplication factor for the flow rate -> distance translation."
-msgstr "Facteur de multiplication pour le débit -> translation de la distance."
+msgid "How far to move the filament in order to compensate for changes in flow rate, as a percentage of how far the filament would move in one second of extrusion."
+msgstr "La distance de déplacement du filament pour compenser les variations du débit, en pourcentage de la distance de déplacement du filament en une seconde"
+" d'extrusion."
#: fdmprinter.def.json
msgctxt "wireframe_enabled label"
@@ -5464,7 +5798,7 @@ msgstr "Distance entre la buse et les lignes descendantes horizontalement. Un es
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr "Utiliser des couches adaptatives"
#: fdmprinter.def.json
@@ -5474,7 +5808,7 @@ msgstr "Cette option calcule la hauteur des couches en fonction de la forme du m
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation label"
-msgid "Adaptive layers maximum variation"
+msgid "Adaptive Layers Maximum Variation"
msgstr "Variation maximale des couches adaptatives"
#: fdmprinter.def.json
@@ -5484,7 +5818,7 @@ msgstr "Hauteur maximale autorisée par rapport à la couche de base."
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation_step label"
-msgid "Adaptive layers variation step size"
+msgid "Adaptive Layers Variation Step Size"
msgstr "Taille des étapes de variation des couches adaptatives"
#: fdmprinter.def.json
@@ -5494,13 +5828,14 @@ msgstr "Différence de hauteur de la couche suivante par rapport à la précéde
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
-msgstr "Limite des couches adaptatives"
+msgid "Adaptive Layers Topography Size"
+msgstr "Taille de la topographie des couches adaptatives"
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold description"
-msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
-msgstr "Limite indiquant d'utiliser ou non une couche plus petite. Ce nombre est comparé à la tangente de la pente la plus raide d'une couche."
+msgid "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together."
+msgstr "Distance horizontale cible entre deux couches adjacentes. La réduction de ce paramètre entraîne l'utilisation de couches plus fines pour rapprocher les"
+" bords des couches."
#: fdmprinter.def.json
msgctxt "wall_overhang_angle label"
@@ -5509,8 +5844,9 @@ msgstr "Angle de parois en porte-à-faux"
#: fdmprinter.def.json
msgctxt "wall_overhang_angle description"
-msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
-msgstr "Les parois ayant un angle supérieur à cette valeur seront imprimées en utilisant les paramètres de parois en porte-à-faux. Si la valeur est 90, aucune paroi ne sera considérée comme étant en porte-à-faux."
+msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging. Overhang that gets supported by support will not be treated as overhang either."
+msgstr "Les parois ayant un angle supérieur à cette valeur seront imprimées en utilisant les paramètres de parois en porte-à-faux. Si la valeur est 90, aucune"
+" paroi ne sera considérée comme étant en porte-à-faux. La saillie soutenue par le support ne sera pas non plus considérée comme étant en porte-à-faux."
#: fdmprinter.def.json
msgctxt "wall_overhang_speed_factor label"
@@ -5712,6 +6048,198 @@ msgctxt "bridge_fan_speed_3 description"
msgid "Percentage fan speed to use when printing the third bridge skin layer."
msgstr "Vitesse du ventilateur en pourcentage à utiliser pour l'impression de la troisième couche extérieure du pont."
+#: fdmprinter.def.json
+msgctxt "clean_between_layers label"
+msgid "Wipe Nozzle Between Layers"
+msgstr "Essuyer la buse entre les couches"
+
+#: fdmprinter.def.json
+msgctxt "clean_between_layers description"
+msgid "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working."
+msgstr "Inclure ou non le G-Code d'essuyage de la buse entre les couches. L'activation de ce paramètre peut influencer le comportement de la rétraction lors du changement de couche. Veuillez utiliser les paramètres de rétraction d'essuyage pour contrôler la rétraction aux couches où le script d'essuyage sera exécuté."
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe label"
+msgid "Material Volume Between Wipes"
+msgstr "Volume de matériau entre les essuyages"
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe description"
+msgid "Maximum material, that can be extruded before another nozzle wipe is initiated."
+msgstr "Le volume maximum de matériau qui peut être extrudé avant qu'un autre essuyage de buse ne soit lancé."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable label"
+msgid "Wipe Retraction Enable"
+msgstr "Activation de la rétraction d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable description"
+msgid "Retract the filament when the nozzle is moving over a non-printed area."
+msgstr "Rétracte le filament quand la buse se déplace vers une zone non imprimée."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount label"
+msgid "Wipe Retraction Distance"
+msgstr "Distance de rétraction d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount description"
+msgid "Amount to retract the filament so it does not ooze during the wipe sequence."
+msgstr "La distance de rétraction du filament afin qu'il ne suinte pas pendant la séquence d'essuyage."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount label"
+msgid "Wipe Retraction Extra Prime Amount"
+msgstr "Degré supplémentaire de rétraction d'essuyage primaire"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount description"
+msgid "Some material can ooze away during a wipe travel moves, which can be compensated for here."
+msgstr "Du matériau peut suinter pendant un déplacement d'essuyage, ce qui peut être compensé ici."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed label"
+msgid "Wipe Retraction Speed"
+msgstr "Vitesse de rétraction d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed description"
+msgid "The speed at which the filament is retracted and primed during a wipe retraction move."
+msgstr "La vitesse à laquelle le filament est rétracté et préparé pendant un déplacement de rétraction d'essuyage."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed label"
+msgid "Wipe Retraction Retract Speed"
+msgstr "Vitesse de rétraction d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed description"
+msgid "The speed at which the filament is retracted during a wipe retraction move."
+msgstr "La vitesse à laquelle le filament est rétracté pendant un déplacement de rétraction d'essuyage."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed label"
+msgid "Retraction Prime Speed"
+msgstr "Vitesse de rétraction primaire"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed description"
+msgid "The speed at which the filament is primed during a wipe retraction move."
+msgstr "La vitesse à laquelle le filament est préparé pendant un déplacement de rétraction d'essuyage."
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause label"
+msgid "Wipe Pause"
+msgstr "Pause d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause description"
+msgid "Pause after the unretract."
+msgstr "Pause après l'irrétraction."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable label"
+msgid "Wipe Z Hop When Retracted"
+msgstr "Décalage en Z d'essuyage lors d’une rétraction"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable description"
+msgid "Whenever a retraction is done, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate."
+msgstr "À chaque rétraction, le plateau est abaissé pour créer un espace entre la buse et l'impression. Cela évite que la buse ne touche l'impression pendant les déplacements, réduisant ainsi le risque de heurter l'impression à partir du plateau."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount label"
+msgid "Wipe Z Hop Height"
+msgstr "Hauteur du décalage en Z d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount description"
+msgid "The height difference when performing a Z Hop."
+msgstr "La différence de hauteur lors de la réalisation d'un décalage en Z."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed label"
+msgid "Wipe Hop Speed"
+msgstr "Vitesse du décalage d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed description"
+msgid "Speed to move the z-axis during the hop."
+msgstr "Vitesse de déplacement de l'axe Z pendant le décalage."
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x label"
+msgid "Wipe Brush X Position"
+msgstr "Position X de la brosse d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x description"
+msgid "X location where wipe script will start."
+msgstr "Emplacement X où le script d'essuyage démarrera."
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count label"
+msgid "Wipe Repeat Count"
+msgstr "Nombre de répétitions d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count description"
+msgid "Number of times to move the nozzle across the brush."
+msgstr "Le nombre de déplacements de la buse à travers la brosse."
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance label"
+msgid "Wipe Move Distance"
+msgstr "Distance de déplacement d'essuyage"
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance description"
+msgid "The distance to move the head back and forth across the brush."
+msgstr "La distance de déplacement de la tête d'avant en arrière à travers la brosse."
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size label"
+msgid "Small Hole Max Size"
+msgstr "Taille maximale des petits trous"
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size description"
+msgid "Holes and part outlines with a diameter smaller than this will be printed using Small Feature Speed."
+msgstr "Les trous et les contours des pièces dont le diamètre est inférieur à celui-ci seront imprimés en utilisant l'option Vitesse de petite structure."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length label"
+msgid "Small Feature Max Length"
+msgstr "Longueur max de petite structure"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length description"
+msgid "Feature outlines that are shorter than this length will be printed using Small Feature Speed."
+msgstr "Les contours des structures dont le diamètre est inférieur à cette longueur seront imprimés en utilisant l'option Vitesse de petite structure."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor label"
+msgid "Small Feature Speed"
+msgstr "Vitesse de petite structure"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor description"
+msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "Les petites structures seront imprimées à ce pourcentage de la vitesse d'impression normale. Une impression plus lente peut aider à l'adhésion et à la"
+" précision."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 label"
+msgid "Small Feature Initial Layer Speed"
+msgstr "Vitesse de la couche initiale de petite structure"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 description"
+msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "Les petites structures sur la première couche seront imprimées à ce pourcentage de la vitesse d'impression normale. Une impression plus lente peut aider"
+" à l'adhésion et à la précision."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5772,6 +6300,218 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Matrice de transformation à appliquer au modèle lors de son chargement depuis le fichier."
+#~ msgctxt "minimum_interface_area description"
+#~ msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Taille minimale de la surface des polygones d'interface de support : les polygones dont la surface est inférieure à cette valeur ne seront pas générés."
+
+#~ msgctxt "minimum_roof_area description"
+#~ msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Taille minimale de la surface des plafonds du support : les polygones dont la surface est inférieure à cette valeur ne seront pas générés."
+
+#~ msgctxt "minimum_bottom_area description"
+#~ msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Taille minimale de la surface des bas du support : les polygones dont la surface est inférieure à cette valeur ne seront pas générés."
+
+#~ msgctxt "skin_alternate_rotation label"
+#~ msgid "Alternate Skin Rotation"
+#~ msgstr "Alterner la rotation dans les couches extérieures"
+
+#~ msgctxt "skin_alternate_rotation description"
+#~ msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
+#~ msgstr "Alterne le sens d'impression des couches du dessus/dessous. Elles sont généralement imprimées uniquement en diagonale. Ce paramètre ajoute les sens X uniquement et Y uniquement."
+
+#~ msgctxt "flow_rate_max_extrusion_offset label"
+#~ msgid "Flow rate compensation max extrusion offset"
+#~ msgstr "Décalage d'extrusion max. pour compensation du débit"
+
+#~ msgctxt "flow_rate_max_extrusion_offset description"
+#~ msgid "The maximum distance in mm to compensate."
+#~ msgstr "Distance de compensation maximum en mm."
+
+#~ msgctxt "flow_rate_extrusion_offset_factor label"
+#~ msgid "Flow rate compensation factor"
+#~ msgstr "Facteur de compensation du débit"
+
+#~ msgctxt "flow_rate_extrusion_offset_factor description"
+#~ msgid "The multiplication factor for the flow rate -> distance translation."
+#~ msgstr "Facteur de multiplication pour le débit -> translation de la distance."
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive Layers Threshold"
+#~ msgstr "Limite des couches adaptatives"
+
+#~ msgctxt "adaptive_layer_height_threshold description"
+#~ msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+#~ msgstr "Limite indiquant d'utiliser ou non une couche plus petite. Ce nombre est comparé à la tangente de la pente la plus raide d'une couche."
+
+#~ msgctxt "wall_overhang_angle description"
+#~ msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
+#~ msgstr "Les parois ayant un angle supérieur à cette valeur seront imprimées en utilisant les paramètres de parois en porte-à-faux. Si la valeur est 90, aucune paroi ne sera considérée comme étant en porte-à-faux."
+
+#~ msgctxt "small_feature_speed_factor description"
+#~ msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "Les petites structures seront imprimées à ce pourcentage de la vitesse d'impression normale. Une impression plus lente peut aider à l'adhésion et à la précision."
+
+#~ msgctxt "small_feature_speed_factor_0 label"
+#~ msgid "First Layer Speed"
+#~ msgstr "Vitesse de la première couche"
+
+#~ msgctxt "small_feature_speed_factor_0 description"
+#~ msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "Les petites structures sur la première couche seront imprimées à ce pourcentage de la vitesse d'impression normale. Une impression plus lente peut aider à l'adhésion et à la précision."
+
+#~ msgctxt "ironing_enabled description"
+#~ msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
+#~ msgstr "Aller au-dessus de la surface supérieure une fois supplémentaire, mais sans extruder de matériau. Cela signifie de faire fondre le plastique en haut un peu plus, pour créer une surface lisse."
+
+#~ msgctxt "start_layers_at_same_position label"
+#~ msgid "Start Layers with the Same Part"
+#~ msgstr "Démarrer les couches avec la même partie"
+
+#~ msgctxt "start_layers_at_same_position description"
+#~ msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
+#~ msgstr "Dans chaque couche, démarre l'impression de l'objet à proximité du même point, de manière à ce que nous ne commencions pas une nouvelle couche en imprimant la pièce avec laquelle la couche précédente s'est terminée. Cela renforce les porte-à-faux et les petites pièces, mais augmente le temps d'impression."
+
+#~ msgctxt "support_infill_angles description"
+#~ msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
+#~ msgstr "Orientation du motif de remplissage pour les supports. Le motif de remplissage du support pivote dans le plan horizontal."
+
+#~ msgctxt "meshfix_maximum_deviation description"
+#~ msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller."
+#~ msgstr "L'écart maximum autorisé lors de la réduction de la résolution pour le paramètre Résolution maximum. Si vous augmentez cette valeur, l'impression sera moins précise, mais le G-Code sera plus petit."
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code Flavour"
+#~ msgstr "Parfum G-Code"
+
+#~ msgctxt "z_seam_corner description"
+#~ msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
+#~ msgstr "Vérifie si les angles du contour du modèle influencent l'emplacement de la jointure. « Aucune » signifie que les angles n'ont aucune influence sur l'emplacement de la jointure. « Masquer jointure » génère généralement le positionnement de la jointure sur un angle intérieur. « Exposer jointure » génère généralement le positionnement de la jointure sur un angle extérieur. « Masquer ou exposer jointure » génère généralement le positionnement de la jointure sur un angle intérieur ou extérieur."
+
+#~ msgctxt "skin_no_small_gaps_heuristic label"
+#~ msgid "Ignore Small Z Gaps"
+#~ msgstr "Ignorer les petits trous en Z"
+
+#~ msgctxt "skin_no_small_gaps_heuristic description"
+#~ msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
+#~ msgstr "Quand le modèle présente de petits trous verticaux, environ 5 % de temps de calcul supplémentaire peut être alloué à la génération de couches du dessus et du dessous dans ces espaces étroits. Dans ce cas, désactivez ce paramètre."
+
+#~ msgctxt "build_volume_temperature description"
+#~ msgid "The temperature used for build volume. If this is 0, the build volume temperature will not be adjusted."
+#~ msgstr "La température utilisée pour le volume d'impression. Si cette valeur est 0, la température du volume d'impression ne sera pas ajustée."
+
+#~ msgctxt "limit_support_retractions description"
+#~ msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+#~ msgstr "Omettre la rétraction lors du passage entre supports en ligne droite. L'activation de ce paramètre permet de gagner du temps lors de l'impression, mais peut conduire à un cordage excessif à l'intérieur de la structure de support."
+
+#~ msgctxt "max_feedrate_z_override label"
+#~ msgid "Maximum Z Speed"
+#~ msgstr "Vitesse Z maximale"
+
+#~ msgctxt "max_feedrate_z_override description"
+#~ msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
+#~ msgstr "La vitesse maximale à laquelle le plateau se déplace. Définir cette valeur sur zéro impose à l'impression d'utiliser les valeurs par défaut du firmware pour la vitesse z maximale."
+
+#~ msgctxt "support_join_distance description"
+#~ msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
+#~ msgstr "La distance maximale entre les supports dans les directions X/Y. Lorsque des supports séparés sont plus rapprochés que cette valeur, ils fusionnent."
+
+#~ msgctxt "support_minimal_diameter label"
+#~ msgid "Minimum Diameter"
+#~ msgstr "Diamètre minimal"
+
+#~ msgctxt "support_minimal_diameter description"
+#~ msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+#~ msgstr "Le diamètre minimal sur les axes X/Y d’une petite zone qui doit être soutenue par une tour de soutien spéciale."
+
+#~ msgctxt "prime_tower_circular label"
+#~ msgid "Circular Prime Tower"
+#~ msgstr "Tour primaire circulaire"
+
+#~ msgctxt "prime_tower_circular description"
+#~ msgid "Make the prime tower as a circular shape."
+#~ msgstr "Réaliser la tour primaire en forme circulaire."
+
+#~ msgctxt "prime_tower_flow description"
+#~ msgid "Flow compensation: the amount of material extruded is multiplied by this value."
+#~ msgstr "Compensation du débit : la quantité de matériau extrudée est multipliée par cette valeur."
+
+#~ msgctxt "smooth_spiralized_contours description"
+#~ msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+#~ msgstr "Lisser les contours spiralisés pour réduire la visibilité de la jointure en Z (la jointure en Z doit être à peine visible sur l'impression mais sera toujours visible dans la vue en couches). Veuillez remarquer que le lissage aura tendance à estomper les détails fins de la surface."
+
+#~ msgctxt "support_conical_enabled description"
+#~ msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
+#~ msgstr "Fonctionnalité expérimentale : rendre les aires de support plus petites en bas qu'au niveau du porte-à-faux à supporter."
+
+#~ msgctxt "extruders_enabled_count label"
+#~ msgid "Number of Extruders that are enabled"
+#~ msgstr "Nombre d'extrudeuses activées"
+
+#~ msgctxt "machine_nozzle_tip_outer_diameter label"
+#~ msgid "Outer nozzle diameter"
+#~ msgstr "Diamètre extérieur de la buse"
+
+#~ msgctxt "machine_nozzle_head_distance label"
+#~ msgid "Nozzle length"
+#~ msgstr "Longueur de la buse"
+
+#~ msgctxt "machine_nozzle_expansion_angle label"
+#~ msgid "Nozzle angle"
+#~ msgstr "Angle de la buse"
+
+#~ msgctxt "machine_heat_zone_length label"
+#~ msgid "Heat zone length"
+#~ msgstr "Longueur de la zone chauffée"
+
+#~ msgctxt "machine_nozzle_heat_up_speed label"
+#~ msgid "Heat up speed"
+#~ msgstr "Vitesse de chauffage"
+
+#~ msgctxt "machine_nozzle_cool_down_speed label"
+#~ msgid "Cool down speed"
+#~ msgstr "Vitesse de refroidissement"
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code flavour"
+#~ msgstr "Parfum G-Code"
+
+#~ msgctxt "machine_disallowed_areas label"
+#~ msgid "Disallowed areas"
+#~ msgstr "Zones interdites"
+
+#~ msgctxt "machine_head_polygon label"
+#~ msgid "Machine head polygon"
+#~ msgstr "Polygone de la tête de machine"
+
+#~ msgctxt "machine_head_with_fans_polygon label"
+#~ msgid "Machine head & Fan polygon"
+#~ msgstr "Tête de la machine et polygone du ventilateur"
+
+#~ msgctxt "gantry_height label"
+#~ msgid "Gantry height"
+#~ msgstr "Hauteur du portique"
+
+#~ msgctxt "machine_use_extruder_offset_to_offset_coords label"
+#~ msgid "Offset With Extruder"
+#~ msgstr "Décalage avec extrudeuse"
+
+#~ msgctxt "adaptive_layer_height_enabled label"
+#~ msgid "Use adaptive layers"
+#~ msgstr "Utiliser des couches adaptatives"
+
+#~ msgctxt "adaptive_layer_height_variation label"
+#~ msgid "Adaptive layers maximum variation"
+#~ msgstr "Variation maximale des couches adaptatives"
+
+#~ msgctxt "adaptive_layer_height_variation_step label"
+#~ msgid "Adaptive layers variation step size"
+#~ msgstr "Taille des étapes de variation des couches adaptatives"
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive layers threshold"
+#~ msgstr "Limite des couches adaptatives"
+
#~ msgctxt "skin_overlap description"
#~ msgid "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall."
#~ msgstr "Le montant de chevauchement entre la couche extérieure et les parois en pourcentage de la largeur de ligne de couche extérieure. Un chevauchement faible permet aux parois de se connecter fermement à la couche extérieure. Ce montant est un pourcentage des largeurs moyennes des lignes de la couche extérieure et de la paroi la plus intérieure."
diff --git a/resources/i18n/it_IT/cura.po b/resources/i18n/it_IT/cura.po
index c857499eb3..b215eae599 100644
--- a/resources/i18n/it_IT/cura.po
+++ b/resources/i18n/it_IT/cura.po
@@ -5,20 +5,20 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
-"PO-Revision-Date: 2018-09-28 15:01+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Italian\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
+"PO-Revision-Date: 2019-07-29 15:51+0100\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: Italian , Italian \n"
"Language: it_IT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.1.1\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr "Impostazioni macchina"
@@ -40,13 +40,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr "File G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr "GCodeWriter non supporta la modalità non di testo."
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr "Preparare il codice G prima dell’esportazione."
@@ -56,7 +56,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "Assistente modello 3D"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,71 +70,50 @@ msgstr ""
"
Scopri come garantire la migliore qualità ed affidabilità di stampa.
"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Changelog"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
-msgstr "Visualizza registro modifiche"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
msgctxt "@action"
msgid "Update Firmware"
msgstr "Aggiornamento firmware"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
-msgctxt "@item:inmenu"
-msgid "Flatten active settings"
-msgstr "Impostazioni attive profilo appiattito"
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "File AMF"
-#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:35
-msgctxt "@info:status"
-msgid "Profile has been flattened & activated."
-msgstr "Il profilo è stato appiattito e attivato."
-
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:33
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Stampa USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:34
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:43
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Stampa tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:35
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:44
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Stampa tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:71
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:80
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Connesso tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:96
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:105
msgctxt "@label"
msgid "A USB print is in progress, closing Cura will stop this print. Are you sure?"
msgstr "Stampa tramite USB in corso, la chiusura di Cura interrompe la stampa. Confermare?"
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/install/X3GWriter/__init__.py:15
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
-msgctxt "X3G Writer File Description"
-msgid "X3G File"
-msgstr "File X3G"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "A print is still in progress. Cura cannot start another print via USB until the previous print has completed."
+msgstr "Stampa ancora in corso. Cura non può avviare un'altra stampa tramite USB finché la precedente non è stata completata."
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
-msgctxt "X3g Writer Plugin Description"
-msgid "Writes X3g to files"
-msgstr "Scrive X3g sui file"
-
-#: /home/ruben/Projects/Cura/plugins/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:21
-msgctxt "X3g Writer File Description"
-msgid "X3g File"
-msgstr "File X3g"
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:127
+msgctxt "@message"
+msgid "Print in Progress"
+msgstr "Stampa in corso"
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
@@ -148,6 +127,7 @@ msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeGzWriter non supporta la modalità di testo."
#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:28
+#: /home/ruben/Projects/Cura/plugins/UFPReader/__init__.py:22
msgctxt "@item:inlistbox"
msgid "Ultimaker Format Package"
msgstr "Pacchetto formato Ultimaker"
@@ -169,7 +149,7 @@ msgid "Save to Removable Drive {0}"
msgstr "Salva su unità rimovibile {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:107
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "Non ci sono formati di file disponibili per la scrittura!"
@@ -206,10 +186,9 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "Impossibile salvare su unità rimovibile {0}: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:152
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1629
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:139
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1668
msgctxt "@info:title"
msgid "Error"
msgstr "Errore"
@@ -238,9 +217,9 @@ msgstr "Rimuovi il dispositivo rimovibile {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:151
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:163
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1619
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1719
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1658
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1758
msgctxt "@info:title"
msgid "Warning"
msgstr "Avvertenza"
@@ -267,337 +246,164 @@ msgctxt "@item:intext"
msgid "Removable Drive"
msgstr "Unità rimovibile"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:74
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterAction.py:26
+msgctxt "@action"
+msgid "Connect via Network"
+msgstr "Collega tramite rete"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:57
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Stampa sulla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:58
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Stampa sulla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
-msgctxt "@info:status"
-msgid "Connected over the network."
-msgstr "Collegato alla rete."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
-msgctxt "@info:status"
-msgid "Connected over the network. Please approve the access request on the printer."
-msgstr "Collegato alla rete. Si prega di approvare la richiesta di accesso sulla stampante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:93
-msgctxt "@info:status"
-msgid "Connected over the network. No access to control the printer."
-msgstr "Collegato alla rete. Nessun accesso per controllare la stampante."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
-msgctxt "@info:status"
-msgid "Access to the printer requested. Please approve the request on the printer"
-msgstr "Richiesto accesso alla stampante. Approvare la richiesta sulla stampante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:101
-msgctxt "@info:title"
-msgid "Authentication status"
-msgstr "Stato di autenticazione"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
-msgctxt "@info:title"
-msgid "Authentication Status"
-msgstr "Stato di autenticazione"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:187
-msgctxt "@action:button"
-msgid "Retry"
-msgstr "Riprova"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
-msgctxt "@info:tooltip"
-msgid "Re-send the access request"
-msgstr "Invia nuovamente la richiesta di accesso"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
-msgctxt "@info:status"
-msgid "Access to the printer accepted"
-msgstr "Accesso alla stampante accettato"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
-msgctxt "@info:status"
-msgid "No access to print with this printer. Unable to send print job."
-msgstr "Nessun accesso per stampare con questa stampante. Impossibile inviare il processo di stampa."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:65
-msgctxt "@action:button"
-msgid "Request Access"
-msgstr "Richiesta di accesso"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:66
-msgctxt "@info:tooltip"
-msgid "Send access request to the printer"
-msgstr "Invia la richiesta di accesso alla stampante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:201
-msgctxt "@label"
-msgid "Unable to start a new print job."
-msgstr "Impossibile avviare un nuovo processo di stampa."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:203
-msgctxt "@label"
-msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
-msgstr "È presente un problema di configurazione della stampante che rende impossibile l’avvio della stampa. Risolvere il problema prima di continuare."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:209
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:231
-msgctxt "@window:title"
-msgid "Mismatched configuration"
-msgstr "Mancata corrispondenza della configurazione"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:223
-msgctxt "@label"
-msgid "Are you sure you wish to print with the selected configuration?"
-msgstr "Sei sicuro di voler stampare con la configurazione selezionata?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:225
-msgctxt "@label"
-msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "Le configurazioni o la calibrazione della stampante e di Cura non corrispondono. Per ottenere i migliori risultati, sezionare sempre per i PrintCore e i materiali inseriti nella stampante utilizzata."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:252
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:162
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:162
-msgctxt "@info:status"
-msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
-msgstr "Invio nuovi processi (temporaneamente) bloccato, invio in corso precedente processo di stampa."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:180
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
-msgctxt "@info:status"
-msgid "Sending data to printer"
-msgstr "Invio dati alla stampante in corso"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:182
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:199
-msgctxt "@info:title"
-msgid "Sending Data"
-msgstr "Invio dati"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:200
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:395
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:38
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:391
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:254
-msgctxt "@action:button"
-msgid "Cancel"
-msgstr "Annulla"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:324
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr "Nessun PrintCore caricato nello slot {slot_number}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:330
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No material loaded in slot {slot_number}"
-msgstr "Nessun materiale caricato nello slot {slot_number}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:353
-#, python-brace-format
-msgctxt "@label"
-msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
-msgstr "PrintCore diverso (Cura: {cura_printcore_name}, Stampante: {remote_printcore_name}) selezionata per estrusore {extruder_id}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:362
-#, python-brace-format
-msgctxt "@label"
-msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr "Materiale diverso (Cura: {0}, Stampante: {1}) selezionato per l’estrusore {2}"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:548
-msgctxt "@window:title"
-msgid "Sync with your printer"
-msgstr "Sincronizzazione con la stampante"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:550
-msgctxt "@label"
-msgid "Would you like to use your current printer configuration in Cura?"
-msgstr "Desideri utilizzare la configurazione corrente della tua stampante in Cura?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:552
-msgctxt "@label"
-msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
-msgstr "I PrintCore e/o i materiali sulla stampante differiscono da quelli contenuti nel tuo attuale progetto. Per ottenere i risultati migliori, sezionare sempre per i PrintCore e i materiali inseriti nella stampante utilizzata."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py:59
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Collegato alla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:275
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:342
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:15
+msgctxt "@info:status"
+msgid "Please wait until the current job has been sent."
+msgstr "Attendere che sia stato inviato il processo corrente."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadBlockedMessage.py:16
+msgctxt "@info:title"
+msgid "Print error"
+msgstr "Errore di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:21
+msgctxt "@info:title"
+msgid "New cloud printers found"
+msgstr "Nuove stampanti in cloud rilevate"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:22
+msgctxt "@info:message"
+msgid "New printers have been found connected to your account, you can find them in your list of discovered printers."
+msgstr "Sono state trovate nuove stampanti collegate al tuo account. Puoi vederle nell'elenco delle stampanti rilevate."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudPrinterDetectedMessage.py:27
+msgctxt "@info:option_text"
+msgid "Do not show this message again"
+msgstr "Non mostrare nuovamente questo messaggio"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:27
+#, python-brace-format
+msgctxt "@info:status"
+msgid "You are attempting to connect to {0} but it is not the host of a group. You can visit the web page to configure it as a group host."
+msgstr "Tentativo di connessione a {0} in corso, che non è l'host di un gruppo. È possibile visitare la pagina web per configurarla come host del gruppo."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:30
+msgctxt "@info:title"
+msgid "Not a group host"
+msgstr "Non host del gruppo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/NotClusterHostMessage.py:35
+msgctxt "@action"
+msgid "Configure group"
+msgstr "Configurare il gruppo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:27
+msgctxt "@info:status"
+msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
+msgstr "Invia e controlla i processi di stampa ovunque con l’account Ultimaker."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:33
+msgctxt "@info:status Ultimaker Cloud should not be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Connettiti a Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/CloudFlowMessage.py:36
+msgctxt "@action"
+msgid "Get started"
+msgstr "Per iniziare"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Invio di un processo di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading print job to printer."
+msgstr "Caricamento del processo di stampa sulla stampante."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:15
msgctxt "@info:status"
msgid "Print job was successfully sent to the printer."
msgstr "Processo di stampa inviato con successo alla stampante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:277
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:343
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py:16
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Dati inviati"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:278
-msgctxt "@action:button"
-msgid "View in Monitor"
-msgstr "Visualizzazione in Controlla"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:390
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:290
-#, python-brace-format
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:18
msgctxt "@info:status"
-msgid "Printer '{printer_name}' has finished printing '{job_name}'."
-msgstr "La stampante '{printer_name}' ha finito di stampare '{job_name}'."
+msgid "You are attempting to connect to a printer that is not running Ultimaker Connect. Please update the printer to the latest firmware."
+msgstr "Si sta tentando di connettersi a una stampante che non esegue Ultimaker Connect. Aggiornare la stampante con il firmware più recente."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:392
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:294
-#, python-brace-format
-msgctxt "@info:status"
-msgid "The print job '{job_name}' was finished."
-msgstr "Il processo di stampa '{job_name}' è terminato."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:393
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:289
-msgctxt "@info:status"
-msgid "Print finished"
-msgstr "Stampa finita"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:573
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:607
-msgctxt "@label:material"
-msgid "Empty"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:574
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:608
-msgctxt "@label:material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:151
-msgctxt "@action:button"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:152
-msgctxt "@properties:tooltip"
-msgid "Print via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:153
-msgctxt "@info:status"
-msgid "Connected via Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:163
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/LegacyDeviceNoLongerSupportedMessage.py:21
msgctxt "@info:title"
-msgid "Cloud error"
-msgstr ""
+msgid "Update your printer"
+msgstr "Aggiornare la stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:180
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:24
+#, python-brace-format
msgctxt "@info:status"
-msgid "Could not export print job."
-msgstr ""
+msgid "Cura has detected material profiles that were not yet installed on the host printer of group {0}."
+msgstr "Cura ha rilevato dei profili di materiale non ancora installati sulla stampante host del gruppo {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:330
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/MaterialSyncMessage.py:26
+msgctxt "@info:title"
+msgid "Sending materials to printer"
+msgstr "Invio dei materiali alla stampante"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:15
msgctxt "@info:text"
msgid "Could not upload the data to the printer."
-msgstr ""
+msgstr "Impossibile caricare i dati sulla stampante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadErrorMessage.py:16
+msgctxt "@info:title"
+msgid "Network error"
+msgstr "Errore di rete"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:27
msgctxt "@info:status"
msgid "tomorrow"
-msgstr ""
+msgstr "domani"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Utils.py:30
msgctxt "@info:status"
msgid "today"
-msgstr ""
+msgstr "oggi"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:151
-msgctxt "@info:description"
-msgid "There was an error connecting to the cloud."
-msgstr ""
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:138
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Stampa tramite Cloud"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:139
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Stampa tramite Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:140
msgctxt "@info:status"
-msgid "Sending data to remote cluster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:456
-msgctxt "@info:status"
-msgid "Send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:460
-msgctxt "@info:status"
-msgid "Connect to Ultimaker Cloud"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:461
-msgctxt "@action"
-msgid "Don't ask me again for this printer."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:464
-msgctxt "@action"
-msgid "Get started"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:478
-msgctxt "@info:status"
-msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:482
-msgctxt "@info:status"
-msgid "Connected!"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:486
-msgctxt "@action"
-msgid "Review your connection"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
-msgctxt "@action"
-msgid "Connect via Network"
-msgstr "Collega tramite rete"
+msgid "Connected via Cloud"
+msgstr "Collegato tramite Cloud"
#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Controlla"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:124
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:125
msgctxt "@info"
msgid "Could not access update information."
msgstr "Non è possibile accedere alle informazioni di aggiornamento."
@@ -624,12 +430,12 @@ msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Visualizzazione strato"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:117
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Cura non visualizza in modo accurato gli strati se la funzione Wire Printing è abilitata"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:118
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vista simulazione"
@@ -637,12 +443,12 @@ msgstr "Vista simulazione"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
msgctxt "@item:inmenu"
msgid "Post Processing"
-msgstr ""
+msgstr "Post-elaborazione"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
msgctxt "@item:inmenu"
msgid "Modify G-Code"
-msgstr ""
+msgstr "Modifica codice G"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12
msgctxt "@label"
@@ -654,46 +460,11 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr "Crea un volume in cui i supporti non vengono stampati."
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr "Cura raccoglie statistiche di utilizzo in forma anonima."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:55
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Acquisizione dati"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:57
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Per saperne di più"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:58
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr "Vedere ulteriori informazioni sui dati inviati da Cura."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:60
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Consenti"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:61
-msgctxt "@action:tooltip"
-msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
-msgstr "Consente a Cura di inviare in forma anonima statistiche d’uso, riguardanti alcune delle preferenze e impostazioni, la versione cura e una serie di modelli in sezionamento, per aiutare a dare priorità a miglioramenti futuri in Cura."
-
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Profili Cura 15.04"
-#: /home/ruben/Projects/Cura/plugins/R2D2/__init__.py:17
-msgctxt "@item:inmenu"
-msgid "Evaluation"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/ImageReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "JPG Image"
@@ -719,56 +490,86 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Immagine GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:15
+msgctxt "@item:inlistbox 'Open' is part of the name of this file format."
+msgid "Open Compressed Triangle Mesh"
+msgstr "Open Compressed Triangle Mesh"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:19
+msgctxt "@item:inlistbox"
+msgid "COLLADA Digital Asset Exchange"
+msgstr "COLLADA Digital Asset Exchange"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:23
+msgctxt "@item:inlistbox"
+msgid "glTF Binary"
+msgstr "glTF Binary"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:27
+msgctxt "@item:inlistbox"
+msgid "glTF Embedded JSON"
+msgstr "glTF Embedded JSON"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:36
+msgctxt "@item:inlistbox"
+msgid "Stanford Triangle Format"
+msgstr "Stanford Triangle Format"
+
+#: /home/ruben/Projects/Cura/plugins/TrimeshReader/__init__.py:40
+msgctxt "@item:inlistbox"
+msgid "Compressed COLLADA Digital Asset Exchange"
+msgstr "Compressed COLLADA Digital Asset Exchange"
+
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
msgctxt "@info:status"
msgid "Unable to slice with the current material as it is incompatible with the selected machine or configuration."
msgstr "Impossibile eseguire il sezionamento con il materiale corrente in quanto incompatibile con la macchina o la configurazione selezionata."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:334
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:389
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:398
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:407
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:416
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:331
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:362
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:386
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:395
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:404
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:413
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "Sezionamento impossibile"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "Impossibile eseguire il sezionamento con le impostazioni attuali. Le seguenti impostazioni presentano errori: {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}"
msgstr "Impossibile eseguire il sezionamento a causa di alcune impostazioni per modello. Le seguenti impostazioni presentano errori su uno o più modelli: {error_labels}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:394
msgctxt "@info:status"
msgid "Unable to slice because the prime tower or prime position(s) are invalid."
msgstr "Impossibile eseguire il sezionamento perché la torre di innesco o la posizione di innesco non sono valide."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid "Unable to slice because there are objects associated with disabled Extruder %s."
msgstr "Impossibile effettuare il sezionamento in quanto vi sono oggetti associati a Extruder %s disabilitato."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:412
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume or are assigned to a disabled extruder. Please scale or rotate models to fit, or enable an extruder."
-msgstr ""
+msgstr "Nulla da sezionare in quanto nessuno dei modelli corrisponde al volume di stampa o è assegnato a un estrusore disabilitato. Ridimensionare o ruotare i modelli secondo necessità o abilitare un estrusore."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Elaborazione dei livelli"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:255
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Informazioni"
@@ -783,12 +584,12 @@ msgctxt "@info:tooltip"
msgid "Configure Per Model Settings"
msgstr "Configura impostazioni per modello"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:186
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Consigliata"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:188
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personalizzata"
@@ -799,19 +600,19 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "File 3MF"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:190
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:763
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:198
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:651
msgctxt "@label"
msgid "Nozzle"
msgstr "Ugello"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:469
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:496
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Project file {0} contains an unknown machine type {1}. Cannot import the machine. Models will be imported instead."
msgstr "Il file di progetto {0} contiene un tipo di macchina sconosciuto {1}. Impossibile importare la macchina. Verranno invece importati i modelli."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:472
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:499
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Apri file progetto"
@@ -826,18 +627,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "File G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:324
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:335
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Parsing codice G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:326
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:476
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:337
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:491
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Dettagli codice G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:474
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:489
msgctxt "@info:generic"
msgid "Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."
msgstr "Verifica che il codice G sia idoneo alla tua stampante e alla sua configurazione prima di trasmettere il file. La rappresentazione del codice G potrebbe non essere accurata."
@@ -845,7 +646,7 @@ msgstr "Verifica che il codice G sia idoneo alla tua stampante e alla sua config
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
msgctxt "@item:inmenu"
msgid "Manage backups"
-msgstr ""
+msgstr "Gestione backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
@@ -858,32 +659,32 @@ msgstr "Backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
msgctxt "@info:backup_status"
msgid "There was an error listing your backups."
-msgstr ""
+msgstr "Si è verificato un errore nell’elenco dei backup."
-#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:121
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:132
msgctxt "@info:backup_status"
msgid "There was an error trying to restore your backup."
-msgstr ""
+msgstr "Si è verificato un errore cercando di ripristinare il backup."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:15
msgctxt "@info:title"
msgid "Backups"
-msgstr ""
+msgstr "Backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
msgctxt "@info:backup_status"
msgid "Uploading your backup..."
-msgstr ""
+msgstr "Caricamento backup in corso..."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:36
msgctxt "@info:backup_status"
msgid "There was an error while uploading your backup."
-msgstr ""
+msgstr "Si è verificato un errore durante il caricamento del backup."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:39
msgctxt "@info:backup_status"
msgid "Your backup has finished uploading."
-msgstr ""
+msgstr "Caricamento backup completato."
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
@@ -891,16 +692,6 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Profilo Cura"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
-msgctxt "@item:inmenu"
-msgid "Profile Assistant"
-msgstr "Assistente profilo"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
-msgctxt "@item:inlistbox"
-msgid "Profile Assistant"
-msgstr "Assistente profilo"
-
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:26
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -919,274 +710,365 @@ msgstr "Errore scrittura file 3MF."
#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
msgctxt "@item:inmenu"
msgid "Preview"
-msgstr ""
+msgstr "Anteprima"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Seleziona aggiornamenti"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
-msgctxt "@action"
-msgid "Checkup"
-msgstr "Controllo"
-
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
msgstr "Livella piano di stampa"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:81
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Parete esterna"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:82
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Pareti interne"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:83
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Rivestimento esterno"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:84
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Riempimento"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:85
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Riempimento del supporto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:86
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Interfaccia supporto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:87
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Supporto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:88
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Skirt"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Spostamenti"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Retrazioni"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Altro"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:309
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "File pre-sezionato {0}"
-
-#: /home/ruben/Projects/Cura/cura/API/Account.py:77
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
msgctxt "@info:title"
msgid "Login failed"
msgstr "Login non riuscito"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:201
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:36
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "Non supportato"
+
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:55
+msgctxt "@info:No intent profile selected"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:196
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:125
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Il file esiste già"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:202
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:197
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:126
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Il file {0} esiste già. Sei sicuro di volerlo sovrascrivere?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:425
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:428
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:433
msgctxt "@info:status"
msgid "Invalid file URL:"
-msgstr ""
+msgstr "File URL non valido:"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:206
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "Non sottoposto a override"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:780
+msgctxt "@info:message Followed by a list of settings."
+msgid "Settings have been changed to match the current availability of extruders:"
+msgstr "Le impostazioni sono state modificate in base all’attuale disponibilità di estrusori:"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:915
-#, python-format
-msgctxt "@info:generic"
-msgid "Settings have been changed to match the current availability of extruders: [%s]"
-msgstr "Le impostazioni sono state modificate in base all’attuale disponibilità di estrusori: [%s]"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:917
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:782
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Impostazioni aggiornate"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1458
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1334
msgctxt "@info:title"
msgid "Extruder(s) Disabled"
-msgstr ""
+msgstr "Estrusore disabilitato"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1457
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:99
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:86
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:182
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:223
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:137
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "Impossibile esportare il profilo su {0}: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:138
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "Impossibile esportare il profilo su {0}: Rilevata anomalia durante scrittura plugin."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:149
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "Profilo esportato su {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:150
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Esportazione riuscita"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr ""
-
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:177
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
-msgid "Can't import profile from {0} before a printer is added."
-msgstr ""
+msgid "Failed to import profile from {0}: {1}"
+msgstr "Impossibile importare il profilo da {0}: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:181
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags !"
+msgid "Can't import profile from {0} before a printer is added."
+msgstr "Impossibile importare il profilo da {0} prima di aggiungere una stampante."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:198
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "No custom profile to import in file {0}"
msgstr "Nessun profilo personalizzato da importare nel file {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:202
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "Failed to import profile from {0}:"
msgstr "Impossibile importare il profilo da {0}:"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:226
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:236
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags !"
msgid "This profile {0} contains incorrect data, could not import it."
msgstr "Questo profilo {0} contiene dati errati, impossibile importarlo."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:241
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:325
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags !"
-msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
-msgstr "La macchina definita nel profilo {0} ({1}) non corrisponde alla macchina corrente ({2}), impossibile importarla."
-
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
-#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to import profile from {0}:"
msgstr "Impossibile importare il profilo da {0}:"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:328
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Profilo importato correttamente {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:319
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:331
#, python-brace-format
msgctxt "@info:status"
msgid "File {0} does not contain any valid profile."
msgstr "Il file {0} non contiene nessun profilo valido."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:322
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:334
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "Il profilo {0} ha un tipo di file sconosciuto o corrotto."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:340
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:369
msgctxt "@label"
msgid "Custom profile"
msgstr "Profilo personalizzato"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:385
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "Il profilo è privo del tipo di qualità."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:370
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:399
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "Impossibile trovare un tipo qualità {0} per la configurazione corrente."
-#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:69
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:76
+msgctxt "@tooltip"
+msgid "Outer Wall"
+msgstr "Parete esterna"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:77
+msgctxt "@tooltip"
+msgid "Inner Walls"
+msgstr "Pareti interne"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:78
+msgctxt "@tooltip"
+msgid "Skin"
+msgstr "Rivestimento esterno"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:79
+msgctxt "@tooltip"
+msgid "Infill"
+msgstr "Riempimento"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:80
+msgctxt "@tooltip"
+msgid "Support Infill"
+msgstr "Riempimento del supporto"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:81
+msgctxt "@tooltip"
+msgid "Support Interface"
+msgstr "Interfaccia supporto"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:82
+msgctxt "@tooltip"
+msgid "Support"
+msgstr "Supporto"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:83
+msgctxt "@tooltip"
+msgid "Skirt"
+msgstr "Skirt"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:84
+msgctxt "@tooltip"
+msgid "Prime Tower"
+msgstr "Torre di innesco"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:85
+msgctxt "@tooltip"
+msgid "Travel"
+msgstr "Spostamenti"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:86
+msgctxt "@tooltip"
+msgid "Retractions"
+msgstr "Retrazioni"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:87
+msgctxt "@tooltip"
+msgid "Other"
+msgstr "Altro"
+
+#: /home/ruben/Projects/Cura/cura/UI/PrintInformation.py:302
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "File pre-sezionato {0}"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Avanti"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:62
#, python-brace-format
msgctxt "@label"
msgid "Group #{group_nr}"
msgstr "Gruppo #{group_nr}"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:65
-msgctxt "@info:title"
-msgid "Network enabled printers"
-msgstr "Stampanti abilitate per la rete"
+#: /home/ruben/Projects/Cura/cura/UI/WhatsNewPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:169
+msgctxt "@action:button"
+msgid "Close"
+msgstr "Chiudi"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/MachineManagementModel.py:80
-msgctxt "@info:title"
-msgid "Local printers"
-msgstr "Stampanti locali"
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:17
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Aggiungi"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
+#: /home/ruben/Projects/Cura/cura/UI/AddPrinterPagesModel.py:18
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:352
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:58
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:149
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:406
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:294
+msgctxt "@action:button"
+msgid "Cancel"
+msgstr "Annulla"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:36
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:320
+msgctxt "@label"
+msgid "Default"
+msgstr "Default"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:39
+msgctxt "@label"
+msgid "Visual"
+msgstr "Visivo"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:40
+msgctxt "@text"
+msgid "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality."
+msgstr "Il profilo visivo è destinato alla stampa di prototipi e modelli visivi, con l'intento di ottenere una qualità visiva e della superficie elevata."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:43
+msgctxt "@label"
+msgid "Engineering"
+msgstr "Engineering"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:44
+msgctxt "@text"
+msgid "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances."
+msgstr "Il profilo di progettazione è destinato alla stampa di prototipi funzionali e di componenti d'uso finale, allo scopo di ottenere maggiore precisione e"
+" tolleranze strette."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:47
+msgctxt "@label"
+msgid "Draft"
+msgstr "Bozza"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/IntentCategoryModel.py:48
+msgctxt "@text"
+msgid "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction."
+msgstr "Il profilo bozza è destinato alla stampa dei prototipi iniziali e alla convalida dei concept, con l'intento di ridurre in modo significativo il tempo di"
+" stampa."
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr "Non sottoposto a override"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:357
+msgctxt "@label"
+msgid "Custom profiles"
+msgstr "Profili personalizzati"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:391
#, python-brace-format
msgctxt "@item:inlistbox"
msgid "All Supported Types ({0})"
msgstr "Tutti i tipi supportati ({0})"
-#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:110
+#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:392
msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Tutti i file (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:665
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:213
msgctxt "@label"
msgid "Custom Material"
msgstr "Materiale personalizzato"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:666
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:256
+#: /home/ruben/Projects/Cura/cura/Machines/Models/MaterialManagementModel.py:214
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:205
msgctxt "@label"
msgid "Custom"
msgstr "Personalizzata"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:116
+msgctxt "@label"
+msgid "The printer(s) below cannot be connected because they are part of a group"
+msgstr "Le stampanti riportate di seguito non possono essere collegate perché fanno parte di un gruppo"
+
+#: /home/ruben/Projects/Cura/cura/Machines/Models/DiscoveredPrintersModel.py:118
+msgctxt "@label"
+msgid "Available networked printers"
+msgstr "Stampanti disponibili in rete"
+
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:90
msgctxt "@info:status"
msgid "The build volume height has been reduced due to the value of the \"Print Sequence\" setting to prevent the gantry from colliding with printed models."
msgstr "L’altezza del volume di stampa è stata ridotta a causa del valore dell’impostazione \"Sequenza di stampa” per impedire la collisione del gantry con i modelli stampati."
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:83
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:92
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volume di stampa"
@@ -1201,52 +1083,67 @@ msgctxt "@info:backup_failed"
msgid "Tried to restore a Cura backup without having proper data or meta data."
msgstr "Tentativo di ripristinare un backup di Cura senza dati o metadati appropriati."
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:124
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:125
msgctxt "@info:backup_failed"
-msgid "Tried to restore a Cura backup that does not match your current version."
-msgstr "Tentativo di ripristinare un backup di Cura non corrispondente alla versione corrente."
+msgid "Tried to restore a Cura backup that is higher than the current version."
+msgstr "Tentativo di ripristinare un backup di Cura di versione superiore rispetto a quella corrente."
-#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:186
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr "Impossibile leggere la risposta."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:201
msgctxt "@info"
msgid "Unable to reach the Ultimaker account server."
-msgstr ""
+msgstr "Impossibile raggiungere il server account Ultimaker."
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:70
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr "Fornire i permessi necessari al momento dell'autorizzazione di questa applicazione."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:77
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
+msgstr "Si è verificato qualcosa di inatteso durante il tentativo di accesso, riprovare."
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:29
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Moltiplicazione e collocazione degli oggetti"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:30
msgctxt "@info:title"
msgid "Placing Objects"
-msgstr ""
+msgstr "Sistemazione oggetti"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:149
msgctxt "@info:status"
msgid "Unable to find a location within the build volume for all objects"
msgstr "Impossibile individuare una posizione nel volume di stampa per tutti gli oggetti"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:108
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Sistemazione oggetto"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:30
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:67
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:66
msgctxt "@info:status"
msgid "Finding new location for objects"
msgstr "Ricerca nuova posizione per gli oggetti"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:34
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:71
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:70
msgctxt "@info:title"
msgid "Finding Location"
msgstr "Ricerca posizione"
#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Impossibile individuare posizione"
@@ -1377,242 +1274,205 @@ msgstr "Registri"
#: /home/ruben/Projects/Cura/cura/CrashHandler.py:322
msgctxt "@title:groupbox"
-msgid "User description"
-msgstr "Descrizione utente"
+msgid "User description (Note: Developers may not speak your language, please use English if possible)"
+msgstr "Descrizione utente (Nota: gli sviluppatori potrebbero non parlare la lingua dell'utente. Se possibile, usare l'inglese)"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:341
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Invia report"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:480
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:513
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Caricamento macchine in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:781
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:520
+msgctxt "@info:progress"
+msgid "Setting up preferences..."
+msgstr "Impostazione delle preferenze..."
+
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:824
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Impostazione scena in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:817
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:859
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Caricamento interfaccia in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1059
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1150
#, python-format
msgctxt "@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm."
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr "%(width).1f x %(depth).1f x %(height).1f mm"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1618
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1657
#, python-brace-format
msgctxt "@info:status"
msgid "Only one G-code file can be loaded at a time. Skipped importing {0}"
msgstr "È possibile caricare un solo file codice G per volta. Importazione saltata {0}"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1628
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1667
#, python-brace-format
msgctxt "@info:status"
msgid "Can't open any other file if G-code is loading. Skipped importing {0}"
msgstr "Impossibile aprire altri file durante il caricamento del codice G. Importazione saltata {0}"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1718
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1757
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "Il modello selezionato è troppo piccolo per il caricamento."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:62
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Impostazioni macchina"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:81
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Stampante"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:100
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:56
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Impostazioni della stampante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:70
msgctxt "@label"
msgid "X (Width)"
msgstr "X (Larghezza)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:112
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:122
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:132
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:387
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:429
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:441
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:897
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:74
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:88
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:102
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:243
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:265
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:285
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:79
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:93
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:109
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:124
msgctxt "@label"
msgid "mm"
msgstr "mm"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:84
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (Profondità)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:98
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (Altezza)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:143
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:112
msgctxt "@label"
msgid "Build plate shape"
msgstr "Forma del piano di stampa"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:152
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:125
+msgctxt "@label"
msgid "Origin at center"
msgstr "Origine al centro"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:160
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:137
+msgctxt "@label"
msgid "Heated bed"
msgstr "Piano riscaldato"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:171
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:149
+msgctxt "@label"
+msgid "Heated build volume"
+msgstr "Volume di stampa riscaldato"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:161
msgctxt "@label"
msgid "G-code flavor"
msgstr "Versione codice G"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:184
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:185
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Impostazioni della testina di stampa"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:199
msgctxt "@label"
msgid "X min"
msgstr "X min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:195
-msgctxt "@tooltip"
-msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distanza tra il lato sinistro della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:219
msgctxt "@label"
msgid "Y min"
msgstr "Y min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:205
-msgctxt "@tooltip"
-msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distanza tra il lato anteriore della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:239
msgctxt "@label"
msgid "X max"
msgstr "X max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:215
-msgctxt "@tooltip"
-msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distanza tra il lato destro della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:261
msgctxt "@label"
msgid "Y max"
msgstr "Y max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:225
-msgctxt "@tooltip"
-msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
-msgstr "Distanza tra il lato posteriore della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:281
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Altezza gantry"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:239
-msgctxt "@tooltip"
-msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
-msgstr "La differenza di altezza tra la punta dell’ugello e il sistema gantry (assi X e Y). Utilizzata per evitare collisioni tra le stampe precedenti e il gantry durante la stampa \"Uno alla volta\"."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:258
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:295
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Numero di estrusori"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:314
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "Start G-code"
msgstr "Codice G avvio"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:324
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr "Comandi codice G da eseguire all’avvio."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:333
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:366
+msgctxt "@title:label"
msgid "End G-code"
msgstr "Codice G fine"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:343
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very end."
-msgstr "Comandi codice G da eseguire alla fine."
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:42
+msgctxt "@title:tab"
+msgid "Printer"
+msgstr "Stampante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:374
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:63
+msgctxt "@title:label"
msgid "Nozzle Settings"
msgstr "Impostazioni ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr "Dimensione ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr "Diametro del materiale compatibile"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:404
-msgctxt "@tooltip"
-msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
-msgstr "Diametro nominale del filamento supportato dalla stampante. Il diametro esatto verrà sovrapposto dal materiale e/o dal profilo."
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:428
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Scostamento X ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:440
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:120
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Scostamento Y ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:452
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:135
msgctxt "@label"
msgid "Cooling Fan Number"
msgstr "Numero ventola di raffreddamento"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:453
-msgctxt "@label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:473
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "Codice G avvio estrusore"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:491
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "Codice G fine estrusore"
@@ -1622,7 +1482,7 @@ msgid "Install"
msgstr "Installazione"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Installa"
@@ -1635,18 +1495,18 @@ msgstr "Impossibile connettersi al database pacchetto Cura. Verificare la connes
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
msgctxt "@label"
msgid "ratings"
-msgstr ""
+msgstr "valori"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:28
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:32
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:30
msgctxt "@title:tab"
msgid "Plugins"
msgstr "Plugin"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:69
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:42
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:361
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:77
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiali"
@@ -1654,54 +1514,51 @@ msgstr "Materiali"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
msgctxt "@label"
msgid "Your rating"
-msgstr ""
+msgstr "I tuoi valori"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:98
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:99
msgctxt "@label"
msgid "Version"
msgstr "Versione"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:105
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:106
msgctxt "@label"
msgid "Last updated"
msgstr "Ultimo aggiornamento"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:112
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:260
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:113
msgctxt "@label"
msgid "Author"
msgstr "Autore"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:119
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:120
msgctxt "@label"
msgid "Downloads"
msgstr "Download"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:181
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:222
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:265
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Sconosciuto"
-
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:56
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to install or update"
-msgstr ""
+msgstr "Log in deve essere installato o aggiornato"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:73
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:80
+msgctxt "@label:The string between and is the highlighted link"
+msgid "Buy material spools"
+msgstr "Acquista bobine di materiale"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:96
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:34
msgctxt "@action:button"
msgid "Update"
msgstr "Aggiorna"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:74
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:97
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:35
msgctxt "@action:button"
msgid "Updating"
msgstr "Aggiornamento in corso"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:75
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:98
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:36
msgctxt "@action:button"
msgid "Updated"
@@ -1710,7 +1567,7 @@ msgstr "Aggiornamento eseguito"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
msgid "Marketplace"
-msgstr ""
+msgstr "Mercato"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1745,12 +1602,12 @@ msgstr "Conferma"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to login first before you can rate"
-msgstr ""
+msgstr "Prima della valutazione è necessario effettuare l’accesso"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
msgctxt "@label"
msgid "You need to install the package before you can rate"
-msgstr ""
+msgstr "Prima della valutazione è necessario installare il pacchetto"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
@@ -1762,22 +1619,22 @@ msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Esci da Cura"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Contributions"
msgstr "Contributi della comunità"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:31
msgctxt "@label"
msgid "Community Plugins"
msgstr "Plugin della comunità"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:43
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml:40
msgctxt "@label"
msgid "Generic Materials"
msgstr "Materiali generici"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:56
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Installa"
@@ -1790,7 +1647,7 @@ msgstr "L'installazione sarà eseguita al riavvio"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:53
msgctxt "@label:The string between and is the highlighted link"
msgid "Log in is required to update"
-msgstr ""
+msgstr "Log in deve essere aggiornato"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
@@ -1833,42 +1690,62 @@ msgctxt "@label"
msgid "Featured"
msgstr "In primo piano"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:34
msgctxt "@label"
msgid "Compatibility"
msgstr "Compatibilità"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:124
+msgctxt "@label:table_header"
+msgid "Machine"
+msgstr "Macchina"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:137
+msgctxt "@label:table_header"
+msgid "Build Plate"
+msgstr "Piano di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:143
+msgctxt "@label:table_header"
+msgid "Support"
+msgstr "Supporto"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:149
+msgctxt "@label:table_header"
+msgid "Quality"
+msgstr "Qualità"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:170
msgctxt "@action:label"
msgid "Technical Data Sheet"
-msgstr ""
+msgstr "Scheda dati tecnici"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:179
msgctxt "@action:label"
msgid "Safety Data Sheet"
-msgstr ""
+msgstr "Scheda dati di sicurezza"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:188
msgctxt "@action:label"
msgid "Printing Guidelines"
-msgstr ""
+msgstr "Linee guida di stampa"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:197
msgctxt "@action:label"
msgid "Website"
-msgstr ""
+msgstr "Sito web"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml:16
msgctxt "@info"
msgid "Fetching packages..."
msgstr "Recupero dei pacchetti..."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:90
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:91
msgctxt "@label"
msgid "Website"
msgstr "Sito web"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:97
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "E-mail"
@@ -1878,22 +1755,6 @@ msgctxt "@info:tooltip"
msgid "Some things could be problematic in this print. Click to see tips for adjustment."
msgstr "Alcune parti potrebbero risultare problematiche in questa stampa. Fare click per visualizzare i suggerimenti per la regolazione."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
-msgctxt "@label"
-msgid "Changelog"
-msgstr "Registro modifiche"
-
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:185
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:85
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:482
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
-msgctxt "@action:button"
-msgid "Close"
-msgstr "Chiudi"
-
#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
msgctxt "@title"
msgid "Update Firmware"
@@ -1969,77 +1830,79 @@ msgctxt "@label"
msgid "Firmware update failed due to missing firmware."
msgstr "Aggiornamento firmware non riuscito per firmware mancante."
-#: /home/ruben/Projects/Cura/plugins/UserAgreement/UserAgreement.qml:16
-msgctxt "@title:window"
-msgid "User Agreement"
-msgstr "Contratto di licenza"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:155
+msgctxt "@label link to Connect and Cloud interfaces"
+msgid "Manage printer"
+msgstr "Gestione stampanti"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:254
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:192
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:183
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
+msgstr "Vetro"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:256
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:514
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:248
msgctxt "@info"
-msgid "These options are not available because you are monitoring a cloud printer."
-msgstr ""
+msgid "Please update your printer's firmware to manage the queue remotely."
+msgstr "Aggiornare il firmware della stampante per gestire la coda da remoto."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:289
msgctxt "@info"
msgid "The webcam is not available because you are monitoring a cloud printer."
-msgstr ""
+msgstr "La webcam non è disponibile perché si sta controllando una stampante cloud."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:301
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:348
msgctxt "@label:status"
msgid "Loading..."
-msgstr ""
+msgstr "Caricamento in corso..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:305
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:352
msgctxt "@label:status"
msgid "Unavailable"
msgstr "Non disponibile"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:309
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:356
msgctxt "@label:status"
msgid "Unreachable"
-msgstr ""
+msgstr "Non raggiungibile"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:360
msgctxt "@label:status"
msgid "Idle"
-msgstr ""
+msgstr "Ferma"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
msgctxt "@label"
msgid "Untitled"
-msgstr ""
+msgstr "Senza titolo"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:373
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:422
msgctxt "@label"
msgid "Anonymous"
-msgstr ""
+msgstr "Anonimo"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:399
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:449
msgctxt "@label:status"
msgid "Requires configuration changes"
-msgstr ""
+msgstr "Richiede modifiche di configurazione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:436
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:487
msgctxt "@action:button"
msgid "Details"
-msgstr ""
+msgstr "Dettagli"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
msgctxt "@label"
msgid "Unavailable printer"
-msgstr ""
+msgstr "Stampante non disponibile"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:134
msgctxt "@label"
msgid "First available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:187
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:132
-msgctxt "@label"
-msgid "Glass"
-msgstr "Vetro"
+msgstr "Primo disponibile"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
msgctxt "@label"
@@ -2048,196 +1911,193 @@ msgstr "Coda di stampa"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
msgctxt "@label link to connect manager"
-msgid "Go to Cura Connect"
-msgstr ""
+msgid "Manage in browser"
+msgstr "Gestisci nel browser"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:100
+msgctxt "@label"
+msgid "There are no print jobs in the queue. Slice and send a job to add one."
+msgstr "Non sono presenti processi di stampa nella coda. Eseguire lo slicing e inviare un processo per aggiungerne uno."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:115
msgctxt "@label"
msgid "Print jobs"
-msgstr ""
+msgstr "Processi di stampa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:131
msgctxt "@label"
msgid "Total print time"
-msgstr ""
+msgstr "Tempo di stampa totale"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:130
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:147
msgctxt "@label"
msgid "Waiting for"
-msgstr ""
+msgstr "In attesa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:246
-msgctxt "@label link to connect manager"
-msgid "View print history"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:46
-msgctxt "@window:title"
-msgid "Existing Connection"
-msgstr "Collegamento esistente"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:48
-msgctxt "@message:text"
-msgid "This printer/group is already added to Cura. Please select another printer/group."
-msgstr "Stampante/gruppo già aggiunto a Cura. Selezionare un’altra stampante o un altro gruppo."
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:65
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Collega alla stampante in rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
msgctxt "@label"
-msgid ""
-"To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
-"\n"
-"Select your printer from the list below:"
-msgstr ""
-"Per stampare direttamente sulla stampante in rete, verificare che la stampante desiderata sia collegata alla rete mediante un cavo di rete o mediante collegamento alla rete WIFI. Se si collega Cura alla stampante, è comunque possibile utilizzare una chiavetta USB per trasferire i file codice G alla stampante.\n"
-"\n"
-"Selezionare la stampante dall’elenco seguente:"
+msgid "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer."
+msgstr "Per stampare direttamente sulla stampante in rete, verificare che la stampante desiderata sia collegata alla rete mediante un cavo di rete o mediante collegamento alla rete WIFI. Se non si esegue il collegamento di Cura alla stampante, è comunque possibile utilizzare una chiavetta USB per trasferire i file codice G alla stampante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Aggiungi"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:57
+msgctxt "@label"
+msgid "Select your printer from the list below:"
+msgstr "Selezionare la stampante dall’elenco seguente:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:97
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:77
msgctxt "@action:button"
msgid "Edit"
msgstr "Modifica"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:108
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:138
msgctxt "@action:button"
msgid "Remove"
msgstr "Rimuovi"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:96
msgctxt "@action:button"
msgid "Refresh"
msgstr "Aggiorna"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:211
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:176
msgctxt "@label"
msgid "If your printer is not listed, read the network printing troubleshooting guide"
msgstr "Se la stampante non è nell’elenco, leggere la guida alla risoluzione dei problemi per la stampa in rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:240
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:258
msgctxt "@label"
msgid "Type"
msgstr "Tipo"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:279
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:274
msgctxt "@label"
msgid "Firmware version"
msgstr "Versione firmware"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:290
msgctxt "@label"
msgid "Address"
msgstr "Indirizzo"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:317
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:263
msgctxt "@label"
msgid "This printer is not set up to host a group of printers."
msgstr "Questa stampante non è predisposta per comandare un gruppo di stampanti."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:267
msgctxt "@label"
msgid "This printer is the host for a group of %1 printers."
msgstr "Questa stampante comanda un gruppo di %1 stampanti."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:332
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:278
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr "La stampante a questo indirizzo non ha ancora risposto."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:337
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
msgctxt "@action:button"
msgid "Connect"
msgstr "Collega"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:351
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:296
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Indirizzo IP non valido"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:146
+msgctxt "@text"
+msgid "Please enter a valid IP address."
+msgstr "Inserire un indirizzo IP valido."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:308
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Indirizzo stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:374
-msgctxt "@alabel"
-msgid "Enter the IP address or hostname of your printer on the network."
-msgstr "Inserire l’indirizzo IP o l’hostname della stampante sulla rete."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
+msgid "Enter the IP address of your printer on the network."
+msgstr "Inserire l'indirizzo IP della stampante in rete."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:404
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:361
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:138
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
msgstr "OK"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
msgctxt "@label:status"
msgid "Aborted"
msgstr "Interrotto"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:90
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:80
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:82
msgctxt "@label:status"
msgid "Finished"
msgstr "Terminato"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:86
msgctxt "@label:status"
msgid "Preparing..."
-msgstr ""
+msgstr "Preparazione in corso..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
msgctxt "@label:status"
msgid "Aborting..."
-msgstr ""
+msgstr "Interr. in corso..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:102
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
msgctxt "@label:status"
msgid "Pausing..."
-msgstr ""
+msgstr "Messa in pausa..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:104
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:94
msgctxt "@label:status"
msgid "Paused"
msgstr "In pausa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:96
msgctxt "@label:status"
msgid "Resuming..."
-msgstr ""
+msgstr "Ripresa in corso..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:108
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:98
msgctxt "@label:status"
msgid "Action required"
msgstr "Richiede un'azione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:110
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:100
msgctxt "@label:status"
msgid "Finishes %1 at %2"
-msgstr ""
+msgstr "Finisce %1 a %2"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:44
-msgctxt "@action:button"
-msgid "Print"
-msgstr "Stampa"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:11
msgctxt "@title:window"
msgid "Print over network"
msgstr "Stampa sulla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:52
+msgctxt "@action:button"
+msgid "Print"
+msgstr "Stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:80
msgctxt "@label"
msgid "Printer selection"
msgstr "Selezione stampante"
@@ -2261,12 +2121,12 @@ msgstr "Riprendi"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
msgctxt "@label"
msgid "Pausing..."
-msgstr ""
+msgstr "Messa in pausa..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
msgctxt "@label"
msgid "Resuming..."
-msgstr ""
+msgstr "Ripresa in corso..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
@@ -2278,7 +2138,7 @@ msgstr "Pausa"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Aborting..."
-msgstr ""
+msgstr "Interr. in corso..."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
@@ -2288,7 +2148,7 @@ msgstr "Interrompi"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:143
msgctxt "@label %1 is the name of a print job."
msgid "Are you sure you want to move %1 to the top of the queue?"
-msgstr "Sei sicuro di voler spostare 1% all’inizio della coda?"
+msgstr "Sei sicuro di voler spostare %1 all’inizio della coda?"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
msgctxt "@window:title"
@@ -2319,161 +2179,156 @@ msgstr "Interrompi la stampa"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
msgctxt "@title:window"
msgid "Configuration Changes"
-msgstr ""
+msgstr "Modifiche configurazione"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
msgctxt "@action:button"
msgid "Override"
-msgstr ""
+msgstr "Override"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:64
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:85
msgctxt "@label"
msgid "The assigned printer, %1, requires the following configuration change:"
msgid_plural "The assigned printer, %1, requires the following configuration changes:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La stampante assegnata, %1, richiede la seguente modifica di configurazione:"
+msgstr[1] "La stampante assegnata, %1, richiede le seguenti modifiche di configurazione:"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:68
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:89
msgctxt "@label"
msgid "The printer %1 is assigned, but the job contains an unknown material configuration."
msgstr "La stampante %1 è assegnata, ma il processo contiene una configurazione materiale sconosciuta."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:78
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:99
msgctxt "@label"
msgid "Change material %1 from %2 to %3."
msgstr "Cambia materiale %1 da %2 a %3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:102
msgctxt "@label"
msgid "Load %3 as material %1 (This cannot be overridden)."
msgstr "Caricare %3 come materiale %1 (Operazione non annullabile)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:84
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:105
msgctxt "@label"
msgid "Change print core %1 from %2 to %3."
msgstr "Cambia print core %1 da %2 a %3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:108
msgctxt "@label"
msgid "Change build plate to %1 (This cannot be overridden)."
msgstr "Cambia piano di stampa a %1 (Operazione non annullabile)."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:94
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:115
msgctxt "@label"
msgid "Override will use the specified settings with the existing printer configuration. This may result in a failed print."
-msgstr ""
+msgstr "L’override utilizza le impostazioni specificate con la configurazione stampante esistente. Ciò può causare una stampa non riuscita."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:135
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:156
msgctxt "@label"
msgid "Aluminum"
msgstr "Alluminio"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:75
-msgctxt "@info:tooltip"
-msgid "Connect to a printer"
-msgstr "Collega a una stampante"
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:92
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:100
msgctxt "@info"
msgid ""
"Please make sure your printer has a connection:\n"
"- Check if the printer is turned on.\n"
-"- Check if the printer is connected to the network."
+"- Check if the printer is connected to the network.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
+"Accertarsi che la stampante sia collegata:\n"
+"- Controllare se la stampante è accesa.\n"
+"- Controllare se la stampante è collegata alla rete.\n"
+"- Controllare se è stato effettuato l'accesso per rilevare le stampanti collegate al cloud."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:110
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
msgctxt "@info"
-msgid "Please select a network connected printer to monitor."
-msgstr ""
+msgid "Please connect your printer to the network."
+msgstr "Collegare la stampante alla rete."
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:126
-msgctxt "@info"
-msgid "Please connect your Ultimaker printer to your local network."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:165
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
msgctxt "@label link to technical assistance"
msgid "View user manuals online"
-msgstr ""
+msgstr "Visualizza i manuali utente online"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:18
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:47
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr "Schema colori"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:105
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Colore materiale"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:109
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Tipo di linea"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:113
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Velocità"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:117
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Spessore strato"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:154
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Modalità di compatibilità"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:229
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
msgid "Travels"
-msgstr ""
+msgstr "Spostamenti"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:235
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
msgid "Helpers"
-msgstr ""
+msgstr "Helper"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:241
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
msgid "Shell"
-msgstr ""
+msgstr "Guscio"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:247
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
msgid "Infill"
msgstr "Riempimento"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Mostra solo strati superiori"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:307
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:308
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr "Mostra 5 strati superiori in dettaglio"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Superiore / Inferiore"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:325
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Parete interna"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:432
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -2503,30 +2358,25 @@ msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Modifica script di post-elaborazione attivi"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:16
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:17
msgctxt "@title:window"
msgid "More information on anonymous data collection"
msgstr "Maggiori informazioni sulla raccolta di dati anonimi"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:66
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:74
msgctxt "@text:window"
-msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
-msgstr "Cura invia dati anonimi ad Ultimaker per migliorare la qualità di stampa e l'esperienza dell'utente. Di seguito è riportato un esempio dei dati inviati."
+msgid "Ultimaker Cura collects anonymous data in order to improve the print quality and user experience. Below is an example of all the data that is shared:"
+msgstr "Ultimaker Cura acquisisce dati anonimi per migliorare la qualità di stampa e l'esperienza dell'utente. Di seguito è riportato un esempio dei dati condivisi:"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:101
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:109
msgctxt "@text:window"
-msgid "I don't want to send this data"
-msgstr ""
+msgid "I don't want to send anonymous data"
+msgstr "Non desidero inviare dati anonimi"
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:111
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:118
msgctxt "@text:window"
-msgid "Allow sending this data to Ultimaker and help us improve Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/R2D2/EvaluationSidebar.qml:49
-msgctxt "@label"
-msgid "No print selected"
-msgstr ""
+msgid "Allow sending anonymous data"
+msgstr "Consenti l'invio di dati anonimi"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
msgctxt "@title:window"
@@ -2575,19 +2425,19 @@ msgstr "Profondità (mm)"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:126
msgctxt "@info:tooltip"
-msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
-msgstr "Per impostazione predefinita, i pixel bianchi rappresentano i punti alti sulla griglia, mentre i pixel neri rappresentano i punti bassi sulla griglia. Modificare questa opzione per invertire la situazione in modo tale che i pixel neri rappresentino i punti alti sulla griglia e i pixel bianchi rappresentino i punti bassi."
-
-#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
-msgctxt "@item:inlistbox"
-msgid "Lighter is higher"
-msgstr "Più chiaro è più alto"
+msgid "For lithophanes dark pixels should correspond to thicker locations in order to block more light coming through. For height maps lighter pixels signify higher terrain, so lighter pixels should correspond to thicker locations in the generated 3D model."
+msgstr "Per le litofanie, i pixel scuri devono corrispondere alle posizioni più spesse per bloccare maggiormente il passaggio della luce. Per le mappe con altezze superiori, i pixel più chiari indicano un terreno più elevato, quindi nel modello 3D generato i pixel più chiari devono corrispondere alle posizioni più spesse."
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
msgctxt "@item:inlistbox"
msgid "Darker is higher"
msgstr "Più scuro è più alto"
+#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:139
+msgctxt "@item:inlistbox"
+msgid "Lighter is higher"
+msgstr "Più chiaro è più alto"
+
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:149
msgctxt "@info:tooltip"
msgid "The amount of smoothing to apply to the image."
@@ -2598,70 +2448,69 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Smoothing"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:37
-msgctxt "@label"
-msgid "Mesh Type"
-msgstr "Tipo di maglia"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:68
-msgctxt "@label"
-msgid "Normal model"
-msgstr "Modello normale"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:75
-msgctxt "@label"
-msgid "Print as support"
-msgstr "Stampa come supporto"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:83
-msgctxt "@label"
-msgid "Don't support overlap with other models"
-msgstr "Non supporta sovrapposizione con altri modelli"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:91
-msgctxt "@label"
-msgid "Modify settings for overlap with other models"
-msgstr "Modifica impostazioni per sovrapposizione con altri modelli"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:99
-msgctxt "@label"
-msgid "Modify settings for infill of other models"
-msgstr "Modifica impostazioni per riempimento di altri modelli"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
-msgctxt "@action:button"
-msgid "Select settings"
-msgstr "Seleziona impostazioni"
-
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:13
msgctxt "@title:window"
msgid "Select Settings to Customize for this model"
msgstr "Seleziona impostazioni di personalizzazione per questo modello"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:431
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:56
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtro..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:445
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/SettingPickDialog.qml:70
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Mostra tutto"
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:44
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Tipo di maglia"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:85
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Modello normale"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:97
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Stampa come supporto"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:109
+msgctxt "@label"
+msgid "Modify settings for overlaps"
+msgstr "Modificare le impostazioni per le sovrapposizioni"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:121
+msgctxt "@label"
+msgid "Don't support overlaps"
+msgstr "Non supportano le sovrapposizioni"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:145
+msgctxt "@action:checkbox"
+msgid "Infill only"
+msgstr "Solo riempimento"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:368
+msgctxt "@action:button"
+msgid "Select settings"
+msgstr "Seleziona impostazioni"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:14
msgctxt "@title:window"
msgid "Open Project"
msgstr "Apri progetto"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:58
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Update/override existing profile"
msgid "Update existing"
msgstr "Aggiorna esistente"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:59
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
-msgctxt "@action:ComboBox option"
+msgctxt "@action:ComboBox Save settings in a new profile"
msgid "Create new"
msgstr "Crea nuovo"
@@ -2688,6 +2537,11 @@ msgctxt "@action:ComboBox option"
msgid "Update"
msgstr "Aggiorna"
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:116
+msgctxt "@action:ComboBox option"
+msgid "Create new"
+msgstr "Crea nuovo"
+
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
@@ -2701,7 +2555,7 @@ msgid "Printer Group"
msgstr "Gruppo stampanti"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:220
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Impostazioni profilo"
@@ -2712,75 +2566,81 @@ msgid "How should the conflict in the profile be resolved?"
msgstr "Come può essere risolto il conflitto nel profilo?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:323
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:221
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:244
msgctxt "@action:label"
msgid "Name"
msgstr "Nome"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:261
+msgctxt "@action:label"
+msgid "Intent"
+msgstr "Intent"
+
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:228
msgctxt "@action:label"
msgid "Not in profile"
msgstr "Non nel profilo"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:210
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:233
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
msgstr[0] "%1 override"
msgstr[1] "%1 override"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:247
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:262
msgctxt "@action:label"
msgid "Derivative from"
msgstr "Derivato da"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:252
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:267
msgctxt "@action:label"
msgid "%1, %2 override"
msgid_plural "%1, %2 overrides"
msgstr[0] "%1, %2 override"
msgstr[1] "%1, %2 override"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:268
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:283
msgctxt "@action:label"
msgid "Material settings"
msgstr "Impostazioni materiale"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:284
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:299
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
msgstr "Come può essere risolto il conflitto nel materiale?"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:342
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Impostazione visibilità"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:336
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:351
msgctxt "@action:label"
msgid "Mode"
msgstr "Modalità"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:367
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Impostazioni visibili:"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:372
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 su %2"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:383
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:398
msgctxt "@action:warning"
msgid "Loading a project will clear all models on the build plate."
msgstr "Il caricamento di un progetto annulla tutti i modelli sul piano di stampa."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:401
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:416
msgctxt "@action:button"
msgid "Open"
msgstr "Apri"
@@ -2788,285 +2648,140 @@ msgstr "Apri"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
msgctxt "@title"
msgid "My Backups"
-msgstr ""
+msgstr "I miei backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:38
msgctxt "@empty_state"
msgid "You don't have any backups currently. Use the 'Backup Now' button to create one."
-msgstr ""
+msgstr "Nessun backup. Usare il pulsante ‘Esegui backup adesso’ per crearne uno."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:60
msgctxt "@backup_limit_info"
msgid "During the preview phase, you'll be limited to 5 visible backups. Remove a backup to see older ones."
-msgstr ""
+msgstr "Durante la fase di anteprima, saranno visibili solo 5 backup. Rimuovi un backup per vedere quelli precedenti."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:34
msgctxt "@description"
msgid "Backup and synchronize your Cura settings."
-msgstr ""
+msgstr "Backup e sincronizzazione delle impostazioni Cura."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:51
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:138
msgctxt "@button"
msgid "Sign in"
-msgstr ""
+msgstr "Accedi"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
msgctxt "@title:window"
msgid "Cura Backups"
-msgstr ""
+msgstr "Backup Cura"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
msgctxt "@backuplist:label"
msgid "Cura Version"
-msgstr ""
+msgstr "Versione Cura"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
msgctxt "@backuplist:label"
msgid "Machines"
-msgstr ""
+msgstr "Macchine"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
msgctxt "@backuplist:label"
msgid "Materials"
-msgstr ""
+msgstr "Materiali"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
msgctxt "@backuplist:label"
msgid "Profiles"
-msgstr ""
+msgstr "Profili"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
msgctxt "@backuplist:label"
msgid "Plugins"
-msgstr ""
+msgstr "Plugin"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
msgctxt "@button"
msgid "Restore"
-msgstr ""
+msgstr "Ripristina"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
msgctxt "@dialog:title"
msgid "Delete Backup"
-msgstr ""
+msgstr "Cancella backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:100
msgctxt "@dialog:info"
msgid "Are you sure you want to delete this backup? This cannot be undone."
-msgstr ""
+msgstr "Sei sicuro di voler cancellare questo backup? Questa operazione non può essere annullata."
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:108
msgctxt "@dialog:title"
msgid "Restore Backup"
-msgstr ""
+msgstr "Ripristina backup"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:109
msgctxt "@dialog:info"
msgid "You will need to restart Cura before your backup is restored. Do you want to close Cura now?"
-msgstr ""
+msgstr "Riavviare Cura prima di ripristinare il backup. Chiudere Cura adesso?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:22
msgctxt "@button"
msgid "Want more?"
-msgstr ""
+msgstr "Ulteriori informazioni?"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
msgctxt "@button"
msgid "Backup Now"
-msgstr ""
+msgstr "Esegui backup adesso"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
msgctxt "@checkbox:description"
msgid "Auto Backup"
-msgstr ""
+msgstr "Backup automatico"
#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:44
msgctxt "@checkbox:description"
msgid "Automatically create a backup each day that Cura is started."
-msgstr ""
+msgstr "Crea automaticamente un backup ogni giorno in cui viene avviata Cura."
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMainSettingsSelector.qml:75
-msgctxt "@label"
-msgid "Not supported"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:35
-msgctxt "@action:button"
-msgid "Previous"
-msgstr "Precedente"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
-msgctxt "@action:button"
-msgid "Export"
-msgstr "Esporta"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Avanti"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:169
-msgctxt "@label"
-msgid "Tip"
-msgstr "Suggerimento"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:160
-msgctxt "@label"
-msgid "Print experiment"
-msgstr "Prova di stampa"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageValidation.qml:25
-msgctxt "@label"
-msgid "Checklist"
-msgstr "Lista di controllo"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:26
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:25
-msgctxt "@title"
-msgid "Select Printer Upgrades"
-msgstr "Seleziona gli aggiornamenti della stampante"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:38
-msgctxt "@label"
-msgid "Please select any upgrades made to this Ultimaker 2."
-msgstr "Seleziona qualsiasi aggiornamento realizzato per questa Ultimaker 2."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
-msgctxt "@label"
-msgid "Olsson Block"
-msgstr "Blocco Olsson"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:30
msgctxt "@title"
msgid "Build Plate Leveling"
msgstr "Livellamento del piano di stampa"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:38
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:44
msgctxt "@label"
msgid "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted."
msgstr "Per assicurarsi stampe di alta qualità, è ora possibile regolare il piano di stampa. Quando si fa clic su 'Spostamento alla posizione successiva' l'ugello si sposterà in diverse posizioni che è possibile regolare."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:57
msgctxt "@label"
msgid "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle."
msgstr "Per ciascuna posizione: inserire un pezzo di carta sotto l'ugello e regolare la stampa dell'altezza del piano di stampa. L'altezza del piano di stampa è corretta quando la carta sfiora la punta dell'ugello."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:62
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:75
msgctxt "@action:button"
msgid "Start Build Plate Leveling"
msgstr "Avvio livellamento del piano di stampa"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:74
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:87
msgctxt "@action:button"
msgid "Move to Next Position"
msgstr "Spostamento alla posizione successiva"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:37
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker Original"
msgstr "Seleziona qualsiasi aggiornamento realizzato per questa Ultimaker Original"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:45
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelectionMachineAction.qml:41
msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Piano di stampa riscaldato (kit ufficiale o integrato)"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
-msgctxt "@title"
-msgid "Check Printer"
-msgstr "Controllo stampante"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
-msgctxt "@label"
-msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
-msgstr "È consigliabile eseguire alcuni controlli di integrità sulla Ultimaker. È possibile saltare questo passaggio se si è certi che la macchina funziona correttamente"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
-msgctxt "@action:button"
-msgid "Start Printer Check"
-msgstr "Avvia controllo stampante"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
-msgctxt "@label"
-msgid "Connection: "
-msgstr "Collegamento: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Connected"
-msgstr "Collegato"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
-msgctxt "@info:status"
-msgid "Not connected"
-msgstr "Non collegato"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
-msgctxt "@label"
-msgid "Min endstop X: "
-msgstr "Endstop min. asse X: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-msgctxt "@info:status"
-msgid "Works"
-msgstr "Funziona"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Not checked"
-msgstr "Controllo non selezionato"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
-msgctxt "@label"
-msgid "Min endstop Y: "
-msgstr "Endstop min. asse Y: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
-msgctxt "@label"
-msgid "Min endstop Z: "
-msgstr "Endstop min. asse Z: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
-msgctxt "@label"
-msgid "Nozzle temperature check: "
-msgstr "Controllo temperatura ugello: "
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Stop Heating"
-msgstr "Arresto riscaldamento"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
-msgctxt "@action:button"
-msgid "Start Heating"
-msgstr "Avvio riscaldamento"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
-msgctxt "@label"
-msgid "Build plate temperature check:"
-msgstr "Controllo temperatura piano di stampa:"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
-msgctxt "@info:status"
-msgid "Checked"
-msgstr "Controllo eseguito"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
-msgctxt "@label"
-msgid "Everything is in order! You're done with your CheckUp."
-msgstr "È tutto in ordine! Controllo terminato."
-
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
@@ -3117,170 +2832,176 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Sei sicuro di voler interrompere la stampa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
msgctxt "@title"
msgid "Information"
msgstr "Informazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
msgctxt "@title:window"
msgid "Confirm Diameter Change"
msgstr "Conferma modifica diametro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:102
msgctxt "@label (%1 is a number)"
msgid "The new filament diameter is set to %1 mm, which is not compatible with the current extruder. Do you wish to continue?"
msgstr "Il nuovo diametro del filamento impostato a %1 mm non è compatibile con l'attuale estrusore. Continuare?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:133
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:128
msgctxt "@label"
msgid "Display Name"
msgstr "Visualizza nome"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:138
msgctxt "@label"
msgid "Brand"
msgstr "Marchio"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:148
msgctxt "@label"
msgid "Material Type"
msgstr "Tipo di materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:158
msgctxt "@label"
msgid "Color"
msgstr "Colore"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:208
msgctxt "@label"
msgid "Properties"
msgstr "Proprietà"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:214
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:210
msgctxt "@label"
msgid "Density"
msgstr "Densità"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:229
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:225
msgctxt "@label"
msgid "Diameter"
msgstr "Diametro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:259
msgctxt "@label"
msgid "Filament Cost"
msgstr "Costo del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:276
msgctxt "@label"
msgid "Filament weight"
msgstr "Peso del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:294
msgctxt "@label"
msgid "Filament length"
msgstr "Lunghezza del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:307
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:303
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Costo al metro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:317
msgctxt "@label"
msgid "This material is linked to %1 and shares some of its properties."
msgstr "Questo materiale è collegato a %1 e condivide alcune delle sue proprietà."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:324
msgctxt "@label"
msgid "Unlink Material"
msgstr "Scollega materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:339
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:335
msgctxt "@label"
msgid "Description"
msgstr "Descrizione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:352
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:348
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Informazioni sull’aderenza"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:17
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
msgctxt "@label"
msgid "Print settings"
msgstr "Impostazioni di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:84
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:84
msgctxt "@action:button"
msgid "Activate"
msgstr "Attiva"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:126
msgctxt "@action:button"
msgid "Create"
msgstr "Crea"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:140
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Duplica"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:141
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:167
msgctxt "@action:button"
msgid "Import"
msgstr "Importa"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:203
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:179
+msgctxt "@action:button"
+msgid "Export"
+msgstr "Esporta"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:233
msgctxt "@action:label"
msgid "Printer"
msgstr "Stampante"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:262
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:246
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:274
msgctxt "@title:window"
msgid "Confirm Remove"
msgstr "Conferma rimozione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:263
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:247
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:300
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:275
msgctxt "@label (%1 is object name)"
msgid "Are you sure you wish to remove %1? This cannot be undone!"
msgstr "Sei sicuro di voler rimuovere %1? Questa operazione non può essere annullata!"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:277
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:285
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:322
msgctxt "@title:window"
msgid "Import Material"
msgstr "Importa materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:323
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Could not import material %1: %2"
msgstr "Impossibile importare materiale {1}: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:327
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully imported material %1"
msgstr "Materiale importato correttamente %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:316
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:345
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:353
msgctxt "@title:window"
msgid "Export Material"
msgstr "Esporta materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:357
msgctxt "@info:status Don't translate the XML tags and !"
msgid "Failed to export material to %1: %2"
msgstr "Impossibile esportare il materiale su %1: %2"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:363
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Materiale esportato correttamente su %1"
@@ -3295,415 +3016,425 @@ msgctxt "@label:textbox"
msgid "Check all"
msgstr "Controlla tutto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:47
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:61
msgctxt "@info:status"
msgid "Calculated"
msgstr "Calcolato"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:75
msgctxt "@title:column"
msgid "Setting"
msgstr "Impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
msgctxt "@title:column"
msgid "Profile"
msgstr "Profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:74
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:89
msgctxt "@title:column"
msgid "Current"
msgstr "Corrente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:82
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfileTab.qml:97
msgctxt "@title:column"
msgid "Unit"
msgstr "Unità"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr "Generale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:126
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:132
msgctxt "@label"
msgid "Interface"
msgstr "Interfaccia"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:143
msgctxt "@label"
msgid "Language:"
msgstr "Lingua:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:210
msgctxt "@label"
msgid "Currency:"
msgstr "Valuta:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:223
msgctxt "@label"
msgid "Theme:"
msgstr "Tema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:273
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:279
msgctxt "@label"
msgid "You will need to restart the application for these changes to have effect."
msgstr "Riavviare l'applicazione per rendere effettive le modifiche."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:296
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Seziona automaticamente alla modifica delle impostazioni."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Seziona automaticamente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:312
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportamento del riquadro di visualizzazione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
msgctxt "@info:tooltip"
msgid "Highlight unsupported areas of the model in red. Without support these areas will not print properly."
msgstr "Evidenzia in rosso le zone non supportate del modello. In assenza di supporto, queste aree non saranno stampate in modo corretto."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:335
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Visualizza sbalzo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:343
msgctxt "@info:tooltip"
msgid "Moves the camera so the model is in the center of the view when a model is selected"
msgstr "Sposta la fotocamera in modo che il modello si trovi al centro della visualizzazione quando è selezionato"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:348
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr "Centratura fotocamera alla selezione dell'elemento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Il comportamento dello zoom predefinito di Cura dovrebbe essere invertito?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:355
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Inverti la direzione dello zoom della fotocamera."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr "Lo zoom si muove nella direzione del mouse?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:379
+msgctxt "@info:tooltip"
+msgid "Zooming towards the mouse is not supported in the orthographic perspective."
+msgstr "Nella prospettiva ortogonale lo zoom verso la direzione del mouse non è supportato."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoom verso la direzione del mouse"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:380
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:410
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved so that they no longer intersect?"
msgstr "I modelli sull’area di stampa devono essere spostati per evitare intersezioni?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:385
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr "Assicurarsi che i modelli siano mantenuti separati"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:394
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:424
msgctxt "@info:tooltip"
msgid "Should models on the platform be moved down to touch the build plate?"
msgstr "I modelli sull’area di stampa devono essere portati a contatto del piano di stampa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:429
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr "Rilascia automaticamente i modelli sul piano di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:411
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr "Visualizza il messaggio di avvertimento sul lettore codice G."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr "Messaggio di avvertimento sul lettore codice G"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:428
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:458
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "Lo strato deve essere forzato in modalità di compatibilità?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:463
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr "Forzare la modalità di compatibilità visualizzazione strato (riavvio necessario)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
+msgctxt "@info:tooltip"
+msgid "Should Cura open at the location it was closed?"
+msgstr "Aprire Cura nel punto in cui è stato chiuso?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
+msgctxt "@option:check"
+msgid "Restore window position on start"
+msgstr "Ripristinare la posizione della finestra all'avvio"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:488
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr "Quale tipo di rendering della fotocamera è necessario utilizzare?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:495
+msgctxt "@window:text"
+msgid "Camera rendering:"
+msgstr "Rendering fotocamera:"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+msgid "Perspective"
+msgstr "Prospettiva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+msgid "Orthographic"
+msgstr "Ortogonale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Apertura e salvataggio file"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:456
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:545
msgctxt "@info:tooltip"
msgid "Should models be scaled to the build volume if they are too large?"
msgstr "I modelli devono essere ridimensionati al volume di stampa, se troppo grandi?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:461
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:550
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Ridimensiona i modelli troppo grandi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:560
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Un modello può apparire eccessivamente piccolo se la sua unità di misura è espressa in metri anziché in millimetri. Questi modelli devono essere aumentati?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:565
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Ridimensiona i modelli eccessivamente piccoli"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr "I modelli devono essere selezionati dopo essere stati caricati?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:491
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:580
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr "Selezionare i modelli dopo il caricamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
msgctxt "@info:tooltip"
msgid "Should a prefix based on the printer name be added to the print job name automatically?"
msgstr "Al nome del processo di stampa deve essere aggiunto automaticamente un prefisso basato sul nome della stampante?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:506
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr "Aggiungi al nome del processo un prefisso macchina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:516
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:605
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr "Quando si salva un file di progetto deve essere visualizzato un riepilogo?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:609
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr "Visualizza una finestra di riepilogo quando si salva un progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Comportamento predefinito all'apertura di un file progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:538
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:627
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Comportamento predefinito all'apertura di un file progetto: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Chiedi sempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:642
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Apri sempre come progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:554
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Importa sempre i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:679
msgctxt "@info:tooltip"
msgid "When you have made changes to a profile and switched to a different one, a dialog will be shown asking whether you want to keep your modifications or not, or you can choose a default behaviour and never show that dialog again."
msgstr "Dopo aver modificato un profilo ed essere passati a un altro, si apre una finestra di dialogo che chiede se mantenere o eliminare le modifiche oppure se scegliere un comportamento predefinito e non visualizzare più tale finestra di dialogo."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:599
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:52
msgctxt "@label"
msgid "Profiles"
msgstr "Profili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:693
msgctxt "@window:text"
msgid "Default behavior for changed setting values when switching to a different profile: "
msgstr "Comportamento predefinito per i valori di impostazione modificati al passaggio a un profilo diverso: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:707
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:157
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Chiedi sempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Elimina sempre le impostazioni modificate"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:709
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr "Trasferisci sempre le impostazioni modificate a un nuovo profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:654
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
msgctxt "@label"
msgid "Privacy"
msgstr "Privacy"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:661
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:750
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr "Cura deve verificare la presenza di eventuali aggiornamenti all’avvio del programma?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:666
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:755
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Controlla aggiornamenti all’avvio"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:676
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:765
msgctxt "@info:tooltip"
msgid "Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored."
msgstr "I dati anonimi sulla stampa devono essere inviati a Ultimaker? Nota, non sono trasmessi o memorizzati modelli, indirizzi IP o altre informazioni personali."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:681
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:770
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Invia informazioni di stampa (anonime)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:690
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:779
msgctxt "@action:button"
msgid "More information"
msgstr "Ulteriori informazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:708
-msgctxt "@label"
-msgid "Experimental"
-msgstr "Sperimentale"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:715
-msgctxt "@info:tooltip"
-msgid "Use multi build plate functionality"
-msgstr "Utilizzare la funzionalità piano di stampa multiplo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
-msgctxt "@option:check"
-msgid "Use multi build plate functionality (restart required)"
-msgstr "Utilizzare la funzionalità piano di stampa multiplo (necessario riavvio)"
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:16
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr "Stampanti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:57
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:63
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
msgctxt "@action:button"
msgid "Rename"
msgstr "Rinomina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:363
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:419
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:104
msgctxt "@label"
msgid "Create"
msgstr "Crea"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@label"
msgid "Duplicate"
msgstr "Duplica"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:202
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Crea profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:176
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:204
msgctxt "@info"
msgid "Please provide a name for this profile."
-msgstr ""
+msgstr "Indica un nome per questo profilo."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:260
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Duplica profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:263
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:291
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Rinomina profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:276
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:304
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Importa profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:333
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Esporta profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:396
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Stampante: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Default profiles"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:413
-msgctxt "@label"
-msgid "Custom profiles"
-msgstr "Profili personalizzati"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:554
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr "Aggiorna il profilo con le impostazioni/esclusioni correnti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:561
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:257
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Elimina le modifiche correnti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:514
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:580
msgctxt "@action:label"
msgid "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below."
msgstr "Questo profilo utilizza le impostazioni predefinite dalla stampante, perciò non ci sono impostazioni/esclusioni nell’elenco riportato di seguito."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:521
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:588
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr "Le impostazioni correnti corrispondono al profilo selezionato."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:606
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Impostazioni globali"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:90
msgctxt "@action:button"
msgid "Marketplace"
-msgstr ""
+msgstr "Mercato"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
@@ -3726,7 +3457,7 @@ msgstr "&Visualizza"
#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
msgctxt "@title:menu menubar:toplevel"
msgid "&Settings"
-msgstr ""
+msgstr "&Impostazioni"
#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
msgctxt "@title:menu menubar:toplevel"
@@ -3743,12 +3474,12 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Help"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
msgctxt "@title:window"
msgid "New project"
msgstr "Nuovo progetto"
-#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:124
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:125
msgctxt "@info:question"
msgid "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings."
msgstr "Sei sicuro di voler aprire un nuovo progetto? Questo cancellerà il piano di stampa e tutte le impostazioni non salvate."
@@ -3760,36 +3491,36 @@ msgstr "Senza titolo"
#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "search settings"
-msgstr ""
+msgid "Search settings"
+msgstr "Impostazioni ricerca"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:462
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Copia valore su tutti gli estrusori"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:474
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:471
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr "Copia tutti i valori modificati su tutti gli estrusori"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Nascondi questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:521
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Nascondi questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Mantieni visibile questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:557
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configura visibilità delle impostazioni..."
@@ -3805,27 +3536,32 @@ msgstr ""
"\n"
"Fare clic per rendere visibili queste impostazioni."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:81
+msgctxt "@label"
+msgid "This setting is not used because all the settings that it influences are overridden."
+msgstr "Questa impostazione non è utilizzata perché tutte le impostazioni che influenza sono sottoposte a override."
+
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:86
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Influisce su"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:91
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Influenzato da"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:166
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:187
msgctxt "@label"
msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders."
msgstr "Questa impostazione è sempre condivisa tra tutti gli estrusori. La sua modifica varierà il valore per tutti gli estrusori."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:191
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr "Questo valore è risolto da valori per estrusore "
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:230
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3836,7 +3572,7 @@ msgstr ""
"\n"
"Fare clic per ripristinare il valore del profilo."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:329
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3847,87 +3583,79 @@ msgstr ""
"\n"
"Fare clic per ripristinare il valore calcolato."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/NoIntentIcon.qml:31
+msgctxt "@label %1 is filled in with the type of a profile. %2 is filled with a list of numbers (eg '1' or '1, 2')"
+msgid "There is no %1 profile for the configuration in extruder %2. The default intent will be used instead"
+msgid_plural "There is no %1 profile for the configurations in extruders %2. The default intent will be used instead"
+msgstr[0] ""
+msgstr[1] ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
msgctxt "@button"
msgid "Recommended"
-msgstr ""
+msgstr "Consigliata"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
msgctxt "@button"
msgid "Custom"
-msgstr ""
+msgstr "Personalizzata"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
msgctxt "@label"
msgid "Gradual infill"
-msgstr ""
+msgstr "Riempimento graduale"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:232
msgctxt "@label"
msgid "Gradual infill will gradually increase the amount of infill towards the top."
msgstr "Un riempimento graduale aumenterà gradualmente la quantità di riempimento verso l'alto."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:29
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:30
msgctxt "@label"
msgid "Support"
-msgstr ""
+msgstr "Supporto"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:71
msgctxt "@label"
msgid "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."
msgstr "Genera strutture per supportare le parti del modello a sbalzo. Senza queste strutture, queste parti collasserebbero durante la stampa."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml:136
-msgctxt "@label"
-msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
-msgstr "Seleziona l’estrusore da utilizzare per la stampa di strutture di supporto. Ciò consentirà di costruire strutture di supporto sotto il modello per evitare cedimenti del modello o di stampare a mezz'aria."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:29
msgctxt "@label"
msgid "Adhesion"
-msgstr ""
+msgstr "Adesione"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml:74
msgctxt "@label"
msgid "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."
msgstr "Abilita stampa di brim o raft. Questa funzione aggiunge un’area piana attorno o sotto l’oggetto, facile da tagliare successivamente."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:175
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Altezza dello strato"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:206
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:81
msgctxt "@tooltip"
msgid "You have modified some profile settings. If you want to change these go to custom mode."
msgstr "Sono state modificate alcune impostazioni del profilo. Per modificarle, andare alla modalità personalizzata."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:355
-msgctxt "@tooltip"
-msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml:449
-msgctxt "@tooltip"
-msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
-msgstr "Un profilo personalizzato è attualmente attivo. Per attivare il cursore qualità, selezionare un profilo di qualità predefinito nella scheda Personalizza"
-
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:13
msgctxt "@label:Should be short"
msgid "On"
-msgstr ""
+msgstr "Inserita"
#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
msgctxt "@label:Should be short"
msgid "Off"
-msgstr ""
+msgstr "Disinserita"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:33
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Sperimentale"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:47
msgctxt "@label"
msgid "Profile"
-msgstr ""
+msgstr "Profilo"
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml:172
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3938,10 +3666,15 @@ msgstr ""
"\n"
"Fare clic per aprire la gestione profili."
-#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml:160
+msgctxt "@label:header"
+msgid "Custom profiles"
+msgstr "Profili personalizzati"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelector.qml:21
msgctxt "@label shown when we load a Gcode file"
-msgid "Print setup disabled. G code file can not be modified."
-msgstr ""
+msgid "Print setup disabled. G-code file can not be modified."
+msgstr "Impostazione di stampa disabilitata. Il file G-code non può essere modificato."
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
@@ -3973,59 +3706,59 @@ msgctxt "@label"
msgid "Send G-code"
msgstr "Invia codice G"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:364
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:365
msgctxt "@tooltip of G-code command input"
msgid "Send a custom G-code command to the connected printer. Press 'enter' to send the command."
msgstr "Invia un comando codice G personalizzato alla stampante connessa. Premere ‘invio’ per inviare il comando."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:41
msgctxt "@label"
msgid "Extruder"
msgstr "Estrusore"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:71
msgctxt "@tooltip"
msgid "The target temperature of the hotend. The hotend will heat up or cool down towards this temperature. If this is 0, the hotend heating is turned off."
msgstr "Temperatura target dell'estremità riscaldata. L'estremità riscaldata si riscalderà o raffredderà sino a questo valore di temperatura. Se questo è 0, l'estremità riscaldata verrà spenta."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:103
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr "La temperatura corrente di questa estremità calda."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:177
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr "La temperatura di preriscaldo dell’estremità calda."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:332
msgctxt "@button Cancel pre-heating"
msgid "Cancel"
msgstr "Annulla"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:344
#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:335
msgctxt "@button"
msgid "Pre-heat"
msgstr "Pre-riscaldo"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:370
msgctxt "@tooltip of pre-heat"
msgid "Heat the hotend in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the hotend to heat up when you're ready to print."
msgstr "Riscalda l’estremità calda prima della stampa. È possibile continuare a regolare la stampa durante il riscaldamento e non è necessario attendere il riscaldamento dell’estremità calda quando si è pronti per la stampa."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:406
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr "Il colore del materiale di questo estrusore."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:438
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Il materiale di questo estrusore."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:470
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "L’ugello inserito in questo estrusore."
@@ -4065,12 +3798,12 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:46
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Preferiti"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:71
msgctxt "@label:category menu label"
msgid "Generic"
msgstr "Generale"
@@ -4090,42 +3823,47 @@ msgctxt "@title:menu menubar:settings"
msgid "&Printer"
msgstr "S&tampante"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:26
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:27
msgctxt "@title:menu"
msgid "&Material"
msgstr "Ma&teriale"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:36
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Imposta come estrusore attivo"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Enable Extruder"
msgstr "Abilita estrusore"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:49
msgctxt "@action:inmenu"
msgid "Disable Extruder"
msgstr "Disabilita estrusore"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:62
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "&Piano di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:65
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profilo"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:19
msgctxt "@action:inmenu menubar:view"
msgid "&Camera position"
msgstr "&Posizione fotocamera"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:35
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:44
+msgctxt "@action:inmenu menubar:view"
+msgid "Camera view"
+msgstr "Visualizzazione fotocamera"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:47
+msgctxt "@action:inmenu menubar:view"
+msgid "Perspective"
+msgstr "Prospettiva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:59
+msgctxt "@action:inmenu menubar:view"
+msgid "Orthographic"
+msgstr "Ortogonale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:80
msgctxt "@action:inmenu menubar:view"
msgid "&Build plate"
msgstr "P&iano di stampa"
@@ -4145,17 +3883,17 @@ msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Gestisci Impostazione visibilità..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:33
msgctxt "@title:menu menubar:file"
msgid "&Save..."
msgstr "&Salva..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:54
msgctxt "@title:menu menubar:file"
msgid "&Export..."
msgstr "&Esporta..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:65
msgctxt "@action:inmenu menubar:file"
msgid "Export Selection..."
msgstr "Esporta selezione..."
@@ -4182,190 +3920,193 @@ msgstr "Numero di copie"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
msgctxt "@header"
msgid "Configurations"
-msgstr ""
+msgstr "Configurazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:112
msgctxt "@label"
msgid "Select configuration"
-msgstr ""
+msgstr "Seleziona configurazione"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:201
-msgctxt "@label"
-msgid "See the material compatibility chart"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:274
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:223
msgctxt "@label"
msgid "Configurations"
-msgstr ""
+msgstr "Configurazioni"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
msgctxt "@label"
msgid "Loading available configurations from the printer..."
-msgstr ""
+msgstr "Caricamento in corso configurazioni disponibili dalla stampante..."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:58
msgctxt "@label"
msgid "The configurations are not available because the printer is disconnected."
-msgstr ""
+msgstr "Le configurazioni non sono disponibili perché la stampante è scollegata."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:25
msgctxt "@header"
msgid "Custom"
-msgstr ""
+msgstr "Personalizzata"
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
msgctxt "@label"
msgid "Printer"
-msgstr ""
+msgstr "Stampante"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:202
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
msgctxt "@label"
msgid "Enabled"
-msgstr ""
+msgstr "Abilitato"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:239
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:251
msgctxt "@label"
msgid "Material"
msgstr "Materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:344
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:378
msgctxt "@label"
msgid "Use glue for better adhesion with this material combination."
-msgstr ""
+msgstr "Utilizzare la colla per una migliore adesione con questa combinazione di materiali."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:128
msgctxt "@label"
msgid "This configuration is not available because %1 is not recognized. Please visit %2 to download the correct material profile."
-msgstr ""
+msgstr "Questa configurazione non è disponibile perché %1 non viene riconosciuto. Visitare %2 per scaricare il profilo materiale corretto."
#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:129
msgctxt "@label"
msgid "Marketplace"
-msgstr ""
+msgstr "Mercato"
#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:15
msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr "Ap&ri recenti"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr "Stampa attiva"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr "Nome del processo"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Tempo di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:169
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr "Tempo residuo stimato"
#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
msgctxt "@label"
-msgid "View types"
-msgstr ""
+msgid "View type"
+msgstr "Visualizza tipo"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
msgctxt "@label"
-msgid "Hi "
-msgstr ""
+msgid "Object list"
+msgstr "Elenco oggetti"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:22
+msgctxt "@label The argument is a username."
+msgid "Hi %1"
+msgstr "Alto %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:33
msgctxt "@button"
msgid "Ultimaker account"
-msgstr ""
+msgstr "Account Ultimaker"
-#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
msgctxt "@button"
msgid "Sign out"
-msgstr ""
+msgstr "Esci"
#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
msgctxt "@action:button"
msgid "Sign in"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:29
-msgctxt "@label"
-msgid "Ultimaker Cloud"
-msgstr ""
+msgstr "Accedi"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
msgctxt "@label"
msgid "The next generation 3D printing workflow"
-msgstr ""
+msgstr "Flusso di stampa 3D di ultima generazione"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:51
msgctxt "@text"
msgid ""
"- Send print jobs to Ultimaker printers outside your local network\n"
"- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
-"- Get exclusive access to material profiles from leading brands"
+"- Get exclusive access to print profiles from leading brands"
msgstr ""
+"- Invia i processi di stampa alle stampanti Ultimaker esterne alla rete locale\n"
+"- Invia le impostazioni Ultimaker Cura nel cloud per usarle ovunque\n"
+"- Ottieni l’accesso esclusivo ai profili di stampa dai principali marchi"
#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
msgctxt "@button"
msgid "Create account"
-msgstr ""
+msgstr "Crea account"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
msgctxt "@label"
msgid "No time estimation available"
-msgstr ""
+msgstr "Nessuna stima di tempo disponibile"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:76
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
msgctxt "@label"
msgid "No cost estimation available"
-msgstr ""
+msgstr "Nessuna stima di costo disponibile"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
msgctxt "@button"
msgid "Preview"
-msgstr ""
+msgstr "Anteprima"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:55
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Sezionamento in corso..."
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:61
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:67
msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
+msgid "Unable to slice"
msgstr "Sezionamento impossibile"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:116
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
+msgctxt "@button"
+msgid "Processing"
+msgstr "Elaborazione in corso"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:103
msgctxt "@button"
msgid "Slice"
-msgstr ""
+msgstr "Sezionamento"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:117
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
msgctxt "@label"
msgid "Start the slicing process"
-msgstr ""
+msgstr "Avvia il processo di sezionamento"
-#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
msgctxt "@button"
msgid "Cancel"
-msgstr ""
+msgstr "Annulla"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
msgctxt "@label"
-msgid "Time specification"
-msgstr ""
+msgid "Time estimation"
+msgstr "Stima del tempo"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
msgctxt "@label"
-msgid "Material specification"
-msgstr ""
+msgid "Material estimation"
+msgstr "Stima del materiale"
#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
msgctxt "@label m for meter"
@@ -4380,292 +4121,306 @@ msgstr "%1g"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Connected printers"
-msgstr ""
+msgstr "Stampanti collegate"
#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
msgctxt "@label"
msgid "Preset printers"
-msgstr ""
+msgstr "Stampanti preimpostate"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:161
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
msgctxt "@button"
msgid "Add printer"
-msgstr ""
+msgstr "Aggiungi stampante"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:173
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
msgctxt "@button"
msgid "Manage printers"
-msgstr ""
+msgstr "Gestione stampanti"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
msgctxt "@action:inmenu"
msgid "Show Online Troubleshooting Guide"
-msgstr ""
+msgstr "Mostra la Guida ricerca e riparazione dei guasti online"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr "Attiva/disattiva schermo intero"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
+msgctxt "@action:inmenu"
+msgid "Exit Full Screen"
+msgstr "Esci da schermo intero"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:103
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Annulla"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:113
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "Ri&peti"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:123
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Esci"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:131
msgctxt "@action:inmenu menubar:view"
msgid "3D View"
msgstr "Visualizzazione 3D"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:138
msgctxt "@action:inmenu menubar:view"
msgid "Front View"
msgstr "Visualizzazione frontale"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:145
msgctxt "@action:inmenu menubar:view"
msgid "Top View"
msgstr "Visualizzazione superiore"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:152
msgctxt "@action:inmenu menubar:view"
msgid "Left Side View"
msgstr "Visualizzazione lato sinistro"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:159
msgctxt "@action:inmenu menubar:view"
msgid "Right Side View"
msgstr "Visualizzazione lato destro"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Configura Cura..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:173
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Aggiungi stampante..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:179
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Gestione stampanti..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Gestione materiali..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:184
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195
msgctxt "@action:inmenu menubar:profile"
msgid "&Update profile with current settings/overrides"
msgstr "&Aggiorna il profilo con le impostazioni/esclusioni correnti"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:192
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Elimina le modifiche correnti"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr "&Crea profilo dalle impostazioni/esclusioni correnti..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Gestione profili..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:229
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Mostra documentazione &online"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:237
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Se&gnala un errore"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:245
+msgctxt "@action:inmenu menubar:help"
+msgid "What's New"
+msgstr "Scopri le novità"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
msgctxt "@action:inmenu menubar:help"
msgid "About..."
msgstr "Informazioni..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:258
msgctxt "@action:inmenu menubar:edit"
msgid "Delete Selected Model"
msgid_plural "Delete Selected Models"
msgstr[0] "Cancella modello selezionato"
msgstr[1] "Cancella modelli selezionati"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:251
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
msgctxt "@action:inmenu menubar:edit"
msgid "Center Selected Model"
msgid_plural "Center Selected Models"
msgstr[0] "Centra modello selezionato"
msgstr[1] "Centra modelli selezionati"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
msgctxt "@action:inmenu menubar:edit"
msgid "Multiply Selected Model"
msgid_plural "Multiply Selected Models"
msgstr[0] "Moltiplica modello selezionato"
msgstr[1] "Moltiplica modelli selezionati"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Elimina modello"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:294
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "C&entra modello su piattaforma"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:283
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:300
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "&Raggruppa modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:303
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:320
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Separa modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:313
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "&Unisci modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "Mo<iplica modello..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:347
msgctxt "@action:inmenu menubar:edit"
msgid "Select All Models"
msgstr "Seleziona tutti i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:357
msgctxt "@action:inmenu menubar:edit"
msgid "Clear Build Plate"
msgstr "Cancellare piano di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:367
msgctxt "@action:inmenu menubar:file"
msgid "Reload All Models"
msgstr "Ricarica tutti i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:359
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:376
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models To All Build Plates"
msgstr "Sistema tutti i modelli su tutti i piani di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:383
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Sistema tutti i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:374
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:391
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Sistema selezione"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:381
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:398
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr "Reimposta tutte le posizioni dei modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:405
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Transformations"
msgstr "Reimposta tutte le trasformazioni dei modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:412
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Apri file..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:420
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Nuovo Progetto..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:427
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Mostra cartella di configurazione"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
msgid "&Marketplace"
-msgstr ""
+msgstr "&Mercato"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:23
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:181
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
msgctxt "@label"
msgid "This package will be installed after restarting."
msgstr "Questo pacchetto sarà installato dopo il riavvio."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Impostazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:486
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:538
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Chiusura di Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:487
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:499
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:551
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr "Sei sicuro di voler uscire da Cura?"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:589
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:19
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Apri file"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:632
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:695
msgctxt "@window:title"
msgid "Install Package"
msgstr "Installa il pacchetto"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:640
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:703
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Apri file"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:643
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:706
msgctxt "@text:window"
msgid "We have found one or more G-Code files within the files you have selected. You can only open one G-Code file at a time. If you want to open a G-Code file, please just select only one."
msgstr "Rilevata la presenza di uno o più file codice G tra i file selezionati. È possibile aprire solo un file codice G alla volta. Se desideri aprire un file codice G, selezionane uno solo."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:713
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:18
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:809
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Aggiungi stampante"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:817
+msgctxt "@title:window"
+msgid "What's New"
+msgstr "Scopri le novità"
+
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
msgctxt "@label %1 is filled in with the name of an extruder"
msgid "Print Selected Model with %1"
@@ -4727,50 +4482,22 @@ msgctxt "@action:button"
msgid "Create New Profile"
msgstr "Crea nuovo profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:78
-msgctxt "@title:tab"
-msgid "Add a printer to Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:92
-msgctxt "@title:tab"
-msgid ""
-"Select the printer you want to use from the list below.\n"
-"\n"
-"If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:249
-msgctxt "@label"
-msgid "Manufacturer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:271
-msgctxt "@label"
-msgid "Printer Name"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AddMachineDialog.qml:294
-msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Aggiungi stampante"
-
#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:15
msgctxt "@title:window"
msgid "About Cura"
msgstr "Informazioni su Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:56
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:57
msgctxt "@label"
msgid "version: %1"
msgstr "versione: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:72
msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing."
msgstr "Soluzione end-to-end per la stampa 3D con filamento fuso."
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:85
msgctxt "@info:credit"
msgid ""
"Cura is developed by Ultimaker B.V. in cooperation with the community.\n"
@@ -4779,122 +4506,122 @@ msgstr ""
"Cura è stato sviluppato da Ultimaker B.V. in cooperazione con la comunità.\n"
"Cura è orgogliosa di utilizzare i seguenti progetti open source:"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
msgctxt "@label"
msgid "Graphical user interface"
msgstr "Interfaccia grafica utente"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
msgctxt "@label"
msgid "Application framework"
msgstr "Struttura applicazione"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
msgctxt "@label"
msgid "G-code generator"
msgstr "Generatore codice G"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:138
msgctxt "@label"
msgid "Interprocess communication library"
msgstr "Libreria di comunicazione intra-processo"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
msgctxt "@label"
msgid "Programming language"
msgstr "Lingua di programmazione"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
msgctxt "@label"
msgid "GUI framework"
msgstr "Struttura GUI"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
msgctxt "@label"
msgid "GUI framework bindings"
msgstr "Vincoli struttura GUI"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
msgctxt "@label"
msgid "C/C++ Binding library"
msgstr "Libreria vincoli C/C++"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
msgctxt "@label"
msgid "Data interchange format"
msgstr "Formato scambio dati"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
msgctxt "@label"
msgid "Support library for scientific computing"
msgstr "Libreria di supporto per calcolo scientifico"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
msgctxt "@label"
msgid "Support library for faster math"
msgstr "Libreria di supporto per calcolo rapido"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
msgctxt "@label"
msgid "Support library for handling STL files"
msgstr "Libreria di supporto per gestione file STL"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
msgctxt "@label"
msgid "Support library for handling planar objects"
msgstr "Libreria di supporto per gestione oggetti planari"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
msgctxt "@label"
msgid "Support library for handling triangular meshes"
msgstr "Libreria di supporto per gestione maglie triangolari"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
msgctxt "@label"
msgid "Support library for analysis of complex networks"
msgstr "Libreria di supporto per l’analisi di reti complesse"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
msgctxt "@label"
msgid "Support library for handling 3MF files"
msgstr "Libreria di supporto per gestione file 3MF"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
msgctxt "@label"
msgid "Support library for file metadata and streaming"
msgstr "Libreria di supporto per metadati file e streaming"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
msgctxt "@label"
msgid "Serial communication library"
msgstr "Libreria di comunicazione seriale"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
msgctxt "@label"
msgid "ZeroConf discovery library"
msgstr "Libreria scoperta ZeroConf"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
msgctxt "@label"
msgid "Polygon clipping library"
msgstr "Libreria ritaglio poligono"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:156
msgctxt "@Label"
msgid "Python HTTP library"
msgstr "Libreria Python HTTP"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
msgctxt "@label"
msgid "Font"
msgstr "Font"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
msgctxt "@label"
msgid "SVG icons"
msgstr "Icone SVG"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:160
msgctxt "@label"
msgid "Linux cross-distribution application deployment"
msgstr "Apertura applicazione distribuzione incrociata Linux"
@@ -4914,27 +4641,27 @@ msgctxt "@title:window"
msgid "Save Project"
msgstr "Salva progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:138
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Piano di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:170
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:177
msgctxt "@action:label"
msgid "Extruder %1"
msgstr "Estrusore %1"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:192
msgctxt "@action:label"
msgid "%1 & material"
msgstr "%1 & materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:243
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:194
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Materiale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:label"
msgid "Don't show project summary on save again"
msgstr "Non mostrare il riepilogo di progetto alla ripetizione di salva"
-#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:262
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:302
msgctxt "@action:button"
msgid "Save"
msgstr "Salva"
@@ -4964,30 +4691,1451 @@ msgctxt "@action:button"
msgid "Import models"
msgstr "Importa i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:210
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Vedi solo il piano di stampa corrente"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
+msgctxt "@label"
+msgid "Empty"
+msgstr "Vuoto"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:226
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "Sistema su tutti i piani di stampa"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
+msgctxt "@label"
+msgid "Add a printer"
+msgstr "Aggiungi una stampante"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:246
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "Sistema il piano di stampa corrente"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
+msgctxt "@label"
+msgid "Add a networked printer"
+msgstr "Aggiungi una stampante in rete"
-#: X3GWriter/plugin.json
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
+msgctxt "@label"
+msgid "Add a non-networked printer"
+msgstr "Aggiungi una stampante non in rete"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:70
+msgctxt "@label"
+msgid "Add printer by IP address"
+msgstr "Aggiungi stampante per indirizzo IP"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:133
+msgctxt "@text"
+msgid "Place enter your printer's IP address."
+msgstr "Inserisci l'indirizzo IP della stampante."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Aggiungi"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:204
+msgctxt "@label"
+msgid "Could not connect to device."
+msgstr "Impossibile connettersi al dispositivo."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:208
+msgctxt "@label"
+msgid "The printer at this address has not responded yet."
+msgstr "La stampante a questo indirizzo non ha ancora risposto."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:240
+msgctxt "@label"
+msgid "This printer cannot be added because it's an unknown printer or it's not the host of a group."
+msgstr "Questa stampante non può essere aggiunta perché è una stampante sconosciuta o non è l'host di un gruppo."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:329
+msgctxt "@button"
+msgid "Back"
+msgstr "Indietro"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:342
+msgctxt "@button"
+msgid "Connect"
+msgstr "Collega"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/FirstStartMachineActionsContent.qml:77
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:123
+msgctxt "@button"
+msgid "Next"
+msgstr "Avanti"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:23
+msgctxt "@label"
+msgid "User Agreement"
+msgstr "Contratto di licenza"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:56
+msgctxt "@button"
+msgid "Agree"
+msgstr "Accetta"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/UserAgreementContent.qml:70
+msgctxt "@button"
+msgid "Decline and close"
+msgstr "Rifiuta e chiudi"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:24
+msgctxt "@label"
+msgid "Help us to improve Ultimaker Cura"
+msgstr "Aiutaci a migliorare Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:57
+msgctxt "@text"
+msgid "Ultimaker Cura collects anonymous data to improve print quality and user experience, including:"
+msgstr "Ultimaker Cura acquisisce dati anonimi per migliorare la qualità di stampa e l'esperienza dell'utente, tra cui:"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:71
+msgctxt "@text"
+msgid "Machine types"
+msgstr "Tipi di macchine"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:77
+msgctxt "@text"
+msgid "Material usage"
+msgstr "Utilizzo dei materiali"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:83
+msgctxt "@text"
+msgid "Number of slices"
+msgstr "Numero di sezionamenti"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:89
+msgctxt "@text"
+msgid "Print settings"
+msgstr "Impostazioni di stampa"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:102
+msgctxt "@text"
+msgid "Data collected by Ultimaker Cura will not contain any personal information."
+msgstr "I dati acquisiti da Ultimaker Cura non conterranno alcuna informazione personale."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DataCollectionsContent.qml:103
+msgctxt "@text"
+msgid "More information"
+msgstr "Ulteriori informazioni"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WhatsNewContent.qml:24
+msgctxt "@label"
+msgid "What's new in Ultimaker Cura"
+msgstr "Scopri le novità in Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:42
+msgctxt "@label"
+msgid "There is no printer found over your network."
+msgstr "Non è stata trovata alcuna stampante sulla rete."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:179
+msgctxt "@label"
+msgid "Refresh"
+msgstr "Aggiorna"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:190
+msgctxt "@label"
+msgid "Add printer by IP"
+msgstr "Aggiungi stampante per IP"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml:223
+msgctxt "@label"
+msgid "Troubleshooting"
+msgstr "Ricerca e riparazione dei guasti"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:211
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Nome stampante"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:224
+msgctxt "@text"
+msgid "Please give your printer a name"
+msgstr "Assegna un nome alla stampante"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:36
+msgctxt "@label"
+msgid "Ultimaker Cloud"
+msgstr "Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:77
+msgctxt "@text"
+msgid "The next generation 3D printing workflow"
+msgstr "Flusso di stampa 3D di ultima generazione"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:94
+msgctxt "@text"
+msgid "- Send print jobs to Ultimaker printers outside your local network"
+msgstr "- Invia i processi di stampa alle stampanti Ultimaker esterne alla rete locale"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:97
+msgctxt "@text"
+msgid "- Store your Ultimaker Cura settings in the cloud for use anywhere"
+msgstr "- Memorizza le impostazioni Ultimaker Cura nel cloud per usarle ovunque"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:100
+msgctxt "@text"
+msgid "- Get exclusive access to print profiles from leading brands"
+msgstr "- Ottieni l'accesso esclusivo ai profili di stampa dai principali marchi"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:119
+msgctxt "@button"
+msgid "Finish"
+msgstr "Fine"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/CloudContent.qml:128
+msgctxt "@button"
+msgid "Create an account"
+msgstr "Crea un account"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:29
+msgctxt "@label"
+msgid "Welcome to Ultimaker Cura"
+msgstr "Benvenuto in Ultimaker Cura"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:47
+msgctxt "@text"
+msgid ""
+"Please follow these steps to set up\n"
+"Ultimaker Cura. This will only take a few moments."
+msgstr ""
+"Segui questa procedura per configurare\n"
+"Ultimaker Cura. Questa operazione richiederà solo pochi istanti."
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/WelcomeContent.qml:58
+msgctxt "@button"
+msgid "Get started"
+msgstr "Per iniziare"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:27
+msgctxt "@info:tooltip"
+msgid "3D View"
+msgstr "Visualizzazione 3D"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:40
+msgctxt "@info:tooltip"
+msgid "Front View"
+msgstr "Visualizzazione frontale"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
+msgctxt "@info:tooltip"
+msgid "Top View"
+msgstr "Visualizzazione superiore"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
+msgctxt "@info:tooltip"
+msgid "Left View"
+msgstr "Vista sinistra"
+
+#: /home/ruben/Projects/Cura/resources/qml/ViewOrientationControls.qml:79
+msgctxt "@info:tooltip"
+msgid "Right View"
+msgstr "Vista destra"
+
+#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
-msgstr "Consente di salvare il sezionamento risultante come un file X3G, per supportare le stampanti che leggono questo formato (Malyan, Makerbot ed altre stampanti basate su firmware Sailfish)."
+msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
+msgstr "Fornisce un modo per modificare le impostazioni della macchina (come il volume di stampa, la dimensione ugello, ecc.)"
-#: X3GWriter/plugin.json
+#: MachineSettingsAction/plugin.json
msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3GWriter"
+msgid "Machine Settings action"
+msgstr "Azione Impostazioni macchina"
+
+#: Toolbox/plugin.json
+msgctxt "description"
+msgid "Find, manage and install new Cura packages."
+msgstr "Trova, gestisce ed installa nuovi pacchetti Cura."
+
+#: Toolbox/plugin.json
+msgctxt "name"
+msgid "Toolbox"
+msgstr "Casella degli strumenti"
+
+#: XRayView/plugin.json
+msgctxt "description"
+msgid "Provides the X-Ray view."
+msgstr "Fornisce la vista a raggi X."
+
+#: XRayView/plugin.json
+msgctxt "name"
+msgid "X-Ray View"
+msgstr "Vista ai raggi X"
+
+#: X3DReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading X3D files."
+msgstr "Fornisce il supporto per la lettura di file X3D."
+
+#: X3DReader/plugin.json
+msgctxt "name"
+msgid "X3D Reader"
+msgstr "Lettore X3D"
+
+#: GCodeWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a file."
+msgstr "Scrive il codice G in un file."
+
+#: GCodeWriter/plugin.json
+msgctxt "name"
+msgid "G-code Writer"
+msgstr "Writer codice G"
+
+#: ModelChecker/plugin.json
+msgctxt "description"
+msgid "Checks models and print configuration for possible printing issues and give suggestions."
+msgstr "Controlla i modelli e la configurazione di stampa per eventuali problematiche di stampa e suggerimenti."
+
+#: ModelChecker/plugin.json
+msgctxt "name"
+msgid "Model Checker"
+msgstr "Controllo modello"
+
+#: FirmwareUpdater/plugin.json
+msgctxt "description"
+msgid "Provides a machine actions for updating firmware."
+msgstr "Fornisce azioni macchina per l’aggiornamento del firmware."
+
+#: FirmwareUpdater/plugin.json
+msgctxt "name"
+msgid "Firmware Updater"
+msgstr "Aggiornamento firmware"
+
+#: AMFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading AMF files."
+msgstr "Fornisce il supporto per la lettura di file 3MF."
+
+#: AMFReader/plugin.json
+msgctxt "name"
+msgid "AMF Reader"
+msgstr "Lettore 3MF"
+
+#: USBPrinting/plugin.json
+msgctxt "description"
+msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
+msgstr "Accetta i G-Code e li invia ad una stampante. I plugin possono anche aggiornare il firmware."
+
+#: USBPrinting/plugin.json
+msgctxt "name"
+msgid "USB printing"
+msgstr "Stampa USB"
+
+#: GCodeGzWriter/plugin.json
+msgctxt "description"
+msgid "Writes g-code to a compressed archive."
+msgstr "Scrive il codice G in un archivio compresso."
+
+#: GCodeGzWriter/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Writer"
+msgstr "Writer codice G compresso"
+
+#: UFPWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing Ultimaker Format Packages."
+msgstr "Fornisce il supporto per la scrittura di pacchetti formato Ultimaker."
+
+#: UFPWriter/plugin.json
+msgctxt "name"
+msgid "UFP Writer"
+msgstr "Writer UFP"
+
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Fornisce una fase di preparazione in Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Fase di preparazione"
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "description"
+msgid "Provides removable drive hotplugging and writing support."
+msgstr "Fornisce il collegamento a caldo dell'unità rimovibile e il supporto per la scrittura."
+
+#: RemovableDriveOutputDevice/plugin.json
+msgctxt "name"
+msgid "Removable Drive Output Device Plugin"
+msgstr "Plugin dispositivo di output unità rimovibile"
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "description"
+msgid "Manages network connections to Ultimaker networked printers."
+msgstr "Gestisce le connessioni di rete alle stampanti Ultimaker in rete."
+
+#: UM3NetworkPrinting/plugin.json
+msgctxt "name"
+msgid "Ultimaker Network Connection"
+msgstr "Connessione di rete Ultimaker"
+
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Fornisce una fase di controllo in Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Fase di controllo"
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "description"
+msgid "Checks for firmware updates."
+msgstr "Controlla disponibilità di aggiornamenti firmware."
+
+#: FirmwareUpdateChecker/plugin.json
+msgctxt "name"
+msgid "Firmware Update Checker"
+msgstr "Controllo aggiornamento firmware"
+
+#: SimulationView/plugin.json
+msgctxt "description"
+msgid "Provides the Simulation view."
+msgstr "Fornisce la vista di simulazione."
+
+#: SimulationView/plugin.json
+msgctxt "name"
+msgid "Simulation View"
+msgstr "Vista simulazione"
+
+#: GCodeGzReader/plugin.json
+msgctxt "description"
+msgid "Reads g-code from a compressed archive."
+msgstr "Legge il codice G da un archivio compresso."
+
+#: GCodeGzReader/plugin.json
+msgctxt "name"
+msgid "Compressed G-code Reader"
+msgstr "Lettore codice G compresso"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "description"
+msgid "Extension that allows for user created scripts for post processing"
+msgstr "Estensione che consente la post-elaborazione degli script creati da utente"
+
+#: PostProcessingPlugin/plugin.json
+msgctxt "name"
+msgid "Post Processing"
+msgstr "Post-elaborazione"
+
+#: SupportEraser/plugin.json
+msgctxt "description"
+msgid "Creates an eraser mesh to block the printing of support in certain places"
+msgstr "Crea una maglia di cancellazione per bloccare la stampa del supporto in alcune posizioni"
+
+#: SupportEraser/plugin.json
+msgctxt "name"
+msgid "Support Eraser"
+msgstr "Cancellazione supporto"
+
+#: UFPReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading Ultimaker Format Packages."
+msgstr "Fornisce il supporto per la lettura di pacchetti formato Ultimaker."
+
+#: UFPReader/plugin.json
+msgctxt "name"
+msgid "UFP Reader"
+msgstr "Lettore UFP"
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "description"
+msgid "Submits anonymous slice info. Can be disabled through preferences."
+msgstr "Invia informazioni su sezionamento anonime Può essere disabilitato tramite le preferenze."
+
+#: SliceInfoPlugin/plugin.json
+msgctxt "name"
+msgid "Slice info"
+msgstr "Informazioni su sezionamento"
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "description"
+msgid "Provides capabilities to read and write XML-based material profiles."
+msgstr "Offre la possibilità di leggere e scrivere profili di materiali basati su XML."
+
+#: XmlMaterialProfile/plugin.json
+msgctxt "name"
+msgid "Material Profiles"
+msgstr "Profili del materiale"
+
+#: LegacyProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from legacy Cura versions."
+msgstr "Fornisce supporto per l'importazione di profili dalle versioni legacy Cura."
+
+#: LegacyProfileReader/plugin.json
+msgctxt "name"
+msgid "Legacy Cura Profile Reader"
+msgstr "Lettore legacy profilo Cura"
+
+#: GCodeProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing profiles from g-code files."
+msgstr "Fornisce supporto per l'importazione di profili da file G-Code."
+
+#: GCodeProfileReader/plugin.json
+msgctxt "name"
+msgid "G-code Profile Reader"
+msgstr "Lettore profilo codice G"
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
+msgstr "Aggiorna le configurazioni da Cura 3.2 a Cura 3.3."
+
+#: VersionUpgrade/VersionUpgrade32to33/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.2 to 3.3"
+msgstr "Aggiornamento della versione da 3.2 a 3.3"
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
+msgstr "Aggiorna le configurazioni da Cura 3.3 a Cura 3.4."
+
+#: VersionUpgrade/VersionUpgrade33to34/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.3 to 3.4"
+msgstr "Aggiornamento della versione da 3.3 a 3.4"
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.3 to Cura 4.4."
+msgstr "Aggiorna le configurazioni da Cura 4.3 a Cura 4.4."
+
+#: VersionUpgrade/VersionUpgrade43to44/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.3 to 4.4"
+msgstr "Aggiornamento della versione da 4.3 a 4.4"
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
+msgstr "Aggiorna le configurazioni da Cura 2.5 a Cura 2.6."
+
+#: VersionUpgrade/VersionUpgrade25to26/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.5 to 2.6"
+msgstr "Aggiornamento della versione da 2.5 a 2.6"
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
+msgstr "Aggiorna le configurazioni da Cura 2.7 a Cura 3.0."
+
+#: VersionUpgrade/VersionUpgrade27to30/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.7 to 3.0"
+msgstr "Aggiornamento della versione da 2.7 a 3.0"
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.5 to Cura 4.0."
+msgstr "Aggiorna le configurazioni da Cura 3.5 a Cura 4.0."
+
+#: VersionUpgrade/VersionUpgrade35to40/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.5 to 4.0"
+msgstr "Aggiornamento della versione da 3.5 a 4.0"
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
+msgstr "Aggiorna le configurazioni da Cura 3.4 a Cura 3.5."
+
+#: VersionUpgrade/VersionUpgrade34to35/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.4 to 3.5"
+msgstr "Aggiornamento della versione da 3.4 a 3.5"
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.0 to Cura 4.1."
+msgstr "Aggiorna le configurazioni da Cura 4.0 a Cura 4.1."
+
+#: VersionUpgrade/VersionUpgrade40to41/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.0 to 4.1"
+msgstr "Aggiornamento della versione da 4.0 a 4.1"
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
+msgstr "Aggiorna le configurazioni da Cura 3.0 a Cura 3.1."
+
+#: VersionUpgrade/VersionUpgrade30to31/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 3.0 to 3.1"
+msgstr "Aggiornamento della versione da 3.0 a 3.1"
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.1 to Cura 4.2."
+msgstr "Aggiorna le configurazioni da Cura 4.1 a Cura 4.2."
+
+#: VersionUpgrade/VersionUpgrade41to42/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.1 to 4.2"
+msgstr "Aggiornamento della versione da 4.1 a 4.2"
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
+msgstr "Aggiorna le configurazioni da Cura 2.6 a Cura 2.7."
+
+#: VersionUpgrade/VersionUpgrade26to27/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.6 to 2.7"
+msgstr "Aggiornamento della versione da 2.6 a 2.7"
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
+msgstr "Aggiorna le configurazioni da Cura 2.1 a Cura 2.2."
+
+#: VersionUpgrade/VersionUpgrade21to22/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.1 to 2.2"
+msgstr "Aggiornamento della versione da 2.1 a 2.2"
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
+msgstr "Aggiorna le configurazioni da Cura 2.2 a Cura 2.4."
+
+#: VersionUpgrade/VersionUpgrade22to24/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 2.2 to 2.4"
+msgstr "Aggiornamento della versione da 2.2 a 2.4"
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "description"
+msgid "Upgrades configurations from Cura 4.2 to Cura 4.3."
+msgstr "Aggiorna le configurazioni da Cura 4.2 a Cura 4.3."
+
+#: VersionUpgrade/VersionUpgrade42to43/plugin.json
+msgctxt "name"
+msgid "Version Upgrade 4.2 to 4.3"
+msgstr "Aggiornamento della versione da 4.2 a 4.3"
+
+#: ImageReader/plugin.json
+msgctxt "description"
+msgid "Enables ability to generate printable geometry from 2D image files."
+msgstr "Abilita la possibilità di generare geometria stampabile da file immagine 2D."
+
+#: ImageReader/plugin.json
+msgctxt "name"
+msgid "Image Reader"
+msgstr "Lettore di immagine"
+
+#: TrimeshReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading model files."
+msgstr "Fornisce supporto per la lettura dei file modello."
+
+#: TrimeshReader/plugin.json
+msgctxt "name"
+msgid "Trimesh Reader"
+msgstr "Trimesh Reader"
+
+#: CuraEngineBackend/plugin.json
+msgctxt "description"
+msgid "Provides the link to the CuraEngine slicing backend."
+msgstr "Fornisce il collegamento al back-end di sezionamento CuraEngine."
+
+#: CuraEngineBackend/plugin.json
+msgctxt "name"
+msgid "CuraEngine Backend"
+msgstr "Back-end CuraEngine"
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "description"
+msgid "Provides the Per Model Settings."
+msgstr "Fornisce le impostazioni per modello."
+
+#: PerObjectSettingsTool/plugin.json
+msgctxt "name"
+msgid "Per Model Settings Tool"
+msgstr "Utilità impostazioni per modello"
+
+#: 3MFReader/plugin.json
+msgctxt "description"
+msgid "Provides support for reading 3MF files."
+msgstr "Fornisce il supporto per la lettura di file 3MF."
+
+#: 3MFReader/plugin.json
+msgctxt "name"
+msgid "3MF Reader"
+msgstr "Lettore 3MF"
+
+#: SolidView/plugin.json
+msgctxt "description"
+msgid "Provides a normal solid mesh view."
+msgstr "Fornisce una normale visualizzazione a griglia compatta."
+
+#: SolidView/plugin.json
+msgctxt "name"
+msgid "Solid View"
+msgstr "Visualizzazione compatta"
+
+#: GCodeReader/plugin.json
+msgctxt "description"
+msgid "Allows loading and displaying G-code files."
+msgstr "Consente il caricamento e la visualizzazione dei file codice G."
+
+#: GCodeReader/plugin.json
+msgctxt "name"
+msgid "G-code Reader"
+msgstr "Lettore codice G"
+
+#: CuraDrive/plugin.json
+msgctxt "description"
+msgid "Backup and restore your configuration."
+msgstr "Effettua il backup o ripristina la configurazione."
+
+#: CuraDrive/plugin.json
+msgctxt "name"
+msgid "Cura Backups"
+msgstr "Backup Cura"
+
+#: CuraProfileWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for exporting Cura profiles."
+msgstr "Fornisce supporto per l'esportazione dei profili Cura."
+
+#: CuraProfileWriter/plugin.json
+msgctxt "name"
+msgid "Cura Profile Writer"
+msgstr "Writer profilo Cura"
+
+#: 3MFWriter/plugin.json
+msgctxt "description"
+msgid "Provides support for writing 3MF files."
+msgstr "Fornisce il supporto per la scrittura di file 3MF."
+
+#: 3MFWriter/plugin.json
+msgctxt "name"
+msgid "3MF Writer"
+msgstr "Writer 3MF"
+
+#: PreviewStage/plugin.json
+msgctxt "description"
+msgid "Provides a preview stage in Cura."
+msgstr "Fornisce una fase di anteprima in Cura."
+
+#: PreviewStage/plugin.json
+msgctxt "name"
+msgid "Preview Stage"
+msgstr "Fase di anteprima"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "description"
+msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
+msgstr "Fornisce azioni macchina per le macchine Ultimaker (come la procedura guidata di livellamento del piano di stampa, la selezione degli aggiornamenti, ecc.)"
+
+#: UltimakerMachineActions/plugin.json
+msgctxt "name"
+msgid "Ultimaker machine actions"
+msgstr "Azioni della macchina Ultimaker"
+
+#: CuraProfileReader/plugin.json
+msgctxt "description"
+msgid "Provides support for importing Cura profiles."
+msgstr "Fornisce supporto per l'importazione dei profili Cura."
+
+#: CuraProfileReader/plugin.json
+msgctxt "name"
+msgid "Cura Profile Reader"
+msgstr "Lettore profilo Cura"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Flatten active settings"
+#~ msgstr "Impostazioni attive profilo appiattito"
+
+#~ msgctxt "@info:status"
+#~ msgid "Profile has been flattened & activated."
+#~ msgstr "Il profilo è stato appiattito e attivato."
+
+#~ msgctxt "X3g Writer Plugin Description"
+#~ msgid "Writes X3g to files"
+#~ msgstr "Scrive X3g sui file"
+
+#~ msgctxt "X3g Writer File Description"
+#~ msgid "X3g File"
+#~ msgstr "File X3g"
+
+#~ msgctxt "X3G Writer File Description"
+#~ msgid "X3G File"
+#~ msgstr "File X3G"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Open Compressed Triangle Mesh"
+#~ msgstr ""
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Profile Assistant"
+#~ msgstr "Assistente profilo"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Profile Assistant"
+#~ msgstr "Assistente profilo"
+
+#~ msgctxt "@action:button"
+#~ msgid "Retry"
+#~ msgstr "Riprova"
+
+#~ msgctxt "@label:table_header"
+#~ msgid "Print Core"
+#~ msgstr "Print Core"
+
+#~ msgctxt "@label"
+#~ msgid "Don't support overlap with other models"
+#~ msgstr "Non supporta sovrapposizione con altri modelli"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for overlap with other models"
+#~ msgstr "Modifica impostazioni per sovrapposizione con altri modelli"
+
+#~ msgctxt "@label"
+#~ msgid "Modify settings for infill of other models"
+#~ msgstr "Modifica impostazioni per riempimento di altri modelli"
+
+#~ msgctxt "@action:ComboBox option"
+#~ msgid "Update existing"
+#~ msgstr "Aggiorna esistente"
+
+#~ msgctxt "@label"
+#~ msgid "Not supported"
+#~ msgstr "Non supportato"
+
+#~ msgctxt "@action:button"
+#~ msgid "Previous"
+#~ msgstr "Precedente"
+
+#~ msgctxt "@label"
+#~ msgid "Tip"
+#~ msgstr "Suggerimento"
+
+#~ msgctxt "@label"
+#~ msgid "Print experiment"
+#~ msgstr "Prova di stampa"
+
+#~ msgctxt "@label"
+#~ msgid "Checklist"
+#~ msgstr "Lista di controllo"
+
+#~ msgctxt "@label"
+#~ msgid "Please select any upgrades made to this Ultimaker 2."
+#~ msgstr "Seleziona qualsiasi aggiornamento realizzato per questa Ultimaker 2."
+
+#~ msgctxt "@label"
+#~ msgid "Olsson Block"
+#~ msgstr "Blocco Olsson"
+
+#~ msgctxt "@window:text"
+#~ msgid "Camera rendering: "
+#~ msgstr "Rendering fotocamera: "
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Use multi build plate functionality"
+#~ msgstr "Utilizzare la funzionalità piano di stampa multiplo"
+
+#~ msgctxt "@option:check"
+#~ msgid "Use multi build plate functionality (restart required)"
+#~ msgstr "Utilizzare la funzionalità piano di stampa multiplo (necessario riavvio)"
+
+#~ msgctxt "@label"
+#~ msgid "Default profiles"
+#~ msgstr "Profili predefiniti"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "search settings"
+#~ msgstr "impostazioni ricerca"
+
+#~ msgctxt "@label"
+#~ msgid "Layer Height"
+#~ msgstr "Altezza dello strato"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile."
+#~ msgstr "Questo profilo di qualità non è disponibile per la configurazione attuale del materiale e degli ugelli. Modificare tali configurazioni per abilitare il profilo di qualità desiderato."
+
+#~ msgctxt "@tooltip"
+#~ msgid "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab"
+#~ msgstr "Un profilo personalizzato è attualmente attivo. Per attivare il cursore qualità, selezionare un profilo di qualità predefinito nella scheda Personalizza"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Build plate"
+#~ msgstr "&Piano di stampa"
+
+#~ msgctxt "@title:settings"
+#~ msgid "&Profile"
+#~ msgstr "&Profilo"
+
+#~ msgctxt "@action:label"
+#~ msgid "Build plate"
+#~ msgstr "Piano di stampa"
+
+#~ msgctxt "description"
+#~ msgid "Dump the contents of all settings to a HTML file."
+#~ msgstr "Scarica contenuto di tutte le impostazioni in un file HTML."
+
+#~ msgctxt "name"
+#~ msgid "God Mode"
+#~ msgstr "Modalità God"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattened quality changes profile."
+#~ msgstr "Crea un profilo appiattito di modifiche di qualità."
+
+#~ msgctxt "name"
+#~ msgid "Profile Flattener"
+#~ msgstr "Appiattitore di profilo"
+
+#~ msgctxt "description"
+#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+#~ msgstr "Consente ai produttori di materiali di creare nuovi profili materiale e di qualità utilizzando una UI drop-in."
+
+#~ msgctxt "name"
+#~ msgid "Print Profile Assistant"
+#~ msgstr "Assistente profilo di stampa"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network."
+#~ msgstr "Collegato alla rete."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. Please approve the access request on the printer."
+#~ msgstr "Collegato alla rete. Si prega di approvare la richiesta di accesso sulla stampante."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected over the network. No access to control the printer."
+#~ msgstr "Collegato alla rete. Nessun accesso per controllare la stampante."
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer requested. Please approve the request on the printer"
+#~ msgstr "Richiesto accesso alla stampante. Approvare la richiesta sulla stampante"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication status"
+#~ msgstr "Stato di autenticazione"
+
+#~ msgctxt "@info:title"
+#~ msgid "Authentication Status"
+#~ msgstr "Stato di autenticazione"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Re-send the access request"
+#~ msgstr "Invia nuovamente la richiesta di accesso"
+
+#~ msgctxt "@info:status"
+#~ msgid "Access to the printer accepted"
+#~ msgstr "Accesso alla stampante accettato"
+
+#~ msgctxt "@info:status"
+#~ msgid "No access to print with this printer. Unable to send print job."
+#~ msgstr "Nessun accesso per stampare con questa stampante. Impossibile inviare il processo di stampa."
+
+#~ msgctxt "@action:button"
+#~ msgid "Request Access"
+#~ msgstr "Richiesta di accesso"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Send access request to the printer"
+#~ msgstr "Invia la richiesta di accesso alla stampante"
+
+#~ msgctxt "@label"
+#~ msgid "Unable to start a new print job."
+#~ msgstr "Impossibile avviare un nuovo processo di stampa."
+
+#~ msgctxt "@label"
+#~ msgid "There is an issue with the configuration of your Ultimaker, which makes it impossible to start the print. Please resolve this issues before continuing."
+#~ msgstr "È presente un problema di configurazione della stampante che rende impossibile l’avvio della stampa. Risolvere il problema prima di continuare."
+
+#~ msgctxt "@window:title"
+#~ msgid "Mismatched configuration"
+#~ msgstr "Mancata corrispondenza della configurazione"
+
+#~ msgctxt "@label"
+#~ msgid "Are you sure you wish to print with the selected configuration?"
+#~ msgstr "Sei sicuro di voler stampare con la configurazione selezionata?"
+
+#~ msgctxt "@label"
+#~ msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "Le configurazioni o la calibrazione della stampante e di Cura non corrispondono. Per ottenere i migliori risultati, sezionare sempre per i PrintCore e i materiali inseriti nella stampante utilizzata."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
+#~ msgstr "Invio nuovi processi (temporaneamente) bloccato, invio in corso precedente processo di stampa."
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to printer"
+#~ msgstr "Invio dati alla stampante in corso"
+
+#~ msgctxt "@info:title"
+#~ msgid "Sending Data"
+#~ msgstr "Invio dati"
+
+#~ msgctxt "@info:status"
+#~ msgid "No Printcore loaded in slot {slot_number}"
+#~ msgstr "Nessun PrintCore caricato nello slot {slot_number}"
+
+#~ msgctxt "@info:status"
+#~ msgid "No material loaded in slot {slot_number}"
+#~ msgstr "Nessun materiale caricato nello slot {slot_number}"
+
+#~ msgctxt "@label"
+#~ msgid "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}"
+#~ msgstr "PrintCore diverso (Cura: {cura_printcore_name}, Stampante: {remote_printcore_name}) selezionata per estrusore {extruder_id}"
+
+#~ msgctxt "@label"
+#~ msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
+#~ msgstr "Materiale diverso (Cura: {0}, Stampante: {1}) selezionato per l’estrusore {2}"
+
+#~ msgctxt "@window:title"
+#~ msgid "Sync with your printer"
+#~ msgstr "Sincronizzazione con la stampante"
+
+#~ msgctxt "@label"
+#~ msgid "Would you like to use your current printer configuration in Cura?"
+#~ msgstr "Desideri utilizzare la configurazione corrente della tua stampante in Cura?"
+
+#~ msgctxt "@label"
+#~ msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
+#~ msgstr "I PrintCore e/o i materiali sulla stampante differiscono da quelli contenuti nel tuo attuale progetto. Per ottenere i risultati migliori, sezionare sempre per i PrintCore e i materiali inseriti nella stampante utilizzata."
+
+#~ msgctxt "@action:button"
+#~ msgid "View in Monitor"
+#~ msgstr "Visualizzazione in Controlla"
+
+#~ msgctxt "@info:status"
+#~ msgid "Printer '{printer_name}' has finished printing '{job_name}'."
+#~ msgstr "La stampante '{printer_name}' ha finito di stampare '{job_name}'."
+
+#~ msgctxt "@info:status"
+#~ msgid "The print job '{job_name}' was finished."
+#~ msgstr "Il processo di stampa '{job_name}' è terminato."
+
+#~ msgctxt "@info:status"
+#~ msgid "Print finished"
+#~ msgstr "Stampa finita"
+
+#~ msgctxt "@label:material"
+#~ msgid "Empty"
+#~ msgstr "Vuoto"
+
+#~ msgctxt "@label:material"
+#~ msgid "Unknown"
+#~ msgstr "Sconosciuto"
+
+#~ msgctxt "@info:title"
+#~ msgid "Cloud error"
+#~ msgstr "Errore cloud"
+
+#~ msgctxt "@info:status"
+#~ msgid "Could not export print job."
+#~ msgstr "Impossibile esportare il processo di stampa."
+
+#~ msgctxt "@info:description"
+#~ msgid "There was an error connecting to the cloud."
+#~ msgstr "Si è verificato un errore di collegamento al cloud."
+
+#~ msgctxt "@info:status"
+#~ msgid "Uploading via Ultimaker Cloud"
+#~ msgstr "Caricamento tramite Ultimaker Cloud"
+
+#~ msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Collegato a Ultimaker Cloud"
+
+#~ msgctxt "@action"
+#~ msgid "Don't ask me again for this printer."
+#~ msgstr "Non chiedere nuovamente per questa stampante."
+
+#~ msgctxt "@info:status"
+#~ msgid "You can now send and monitor print jobs from anywhere using your Ultimaker account."
+#~ msgstr "Ora è possibile inviare e controllare i processi di stampa ovunque con l’account Ultimaker."
+
+#~ msgctxt "@info:status"
+#~ msgid "Connected!"
+#~ msgstr "Collegato!"
+
+#~ msgctxt "@action"
+#~ msgid "Review your connection"
+#~ msgstr "Controlla collegamento"
+
+#~ msgctxt "@info:status Don't translate the XML tags !"
+#~ msgid "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it."
+#~ msgstr "La macchina definita nel profilo {0} ({1}) non corrisponde alla macchina corrente ({2}), impossibile importarla."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}:"
+#~ msgstr "Impossibile importare il profilo da {0}:"
+
+#~ msgctxt "@window:title"
+#~ msgid "Existing Connection"
+#~ msgstr "Collegamento esistente"
+
+#~ msgctxt "@message:text"
+#~ msgid "This printer/group is already added to Cura. Please select another printer/group."
+#~ msgstr "Stampante/gruppo già aggiunto a Cura. Selezionare un’altra stampante o un altro gruppo."
+
+#~ msgctxt "@label"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Inserire l’indirizzo IP o l’hostname della stampante sulla rete."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Connect to a printer"
+#~ msgstr "Collega a una stampante"
+
+#~ msgctxt "@title"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Guida alle impostazioni Cura"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Zooming towards the mouse is not supported in the orthogonal perspective."
+#~ msgstr "Nella prospettiva ortogonale lo zoom verso la direzione del mouse non è supportato."
+
+#~ msgid "Orthogonal"
+#~ msgstr "Ortogonale"
+
+#~ msgctxt "description"
+#~ msgid "Manages network connections to Ultimaker 3 printers."
+#~ msgstr "Gestisce le connessioni di rete alle stampanti Ultimaker 3."
+
+#~ msgctxt "name"
+#~ msgid "UM3 Network Connection"
+#~ msgstr "Connessione di rete UM3"
+
+#~ msgctxt "description"
+#~ msgid "Provides extra information and explanations about settings in Cura, with images and animations."
+#~ msgstr "Fornisce informazioni e spiegazioni aggiuntive sulle impostazioni in Cura, con immagini e animazioni."
+
+#~ msgctxt "name"
+#~ msgid "Settings Guide"
+#~ msgstr "Guida alle impostazioni"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Cura Settings Guide"
+#~ msgstr "Guida alle impostazioni Cura"
+
+#~ msgctxt "@info:generic"
+#~ msgid "Settings have been changed to match the current availability of extruders: [%s]"
+#~ msgstr "Le impostazioni sono state modificate in base all’attuale disponibilità di estrusori: [%s]"
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "User description"
+#~ msgstr "Descrizione utente"
+
+#~ msgctxt "@info"
+#~ msgid "These options are not available because you are monitoring a cloud printer."
+#~ msgstr "Queste opzioni non sono disponibili perché si sta controllando una stampante cloud."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Go to Cura Connect"
+#~ msgstr "Vai a Cura Connect"
+
+#~ msgctxt "@info"
+#~ msgid "All jobs are printed."
+#~ msgstr "Tutti i processi sono stampati."
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "View print history"
+#~ msgstr "Visualizza cronologia di stampa"
+
+#~ msgctxt "@label"
+#~ msgid ""
+#~ "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n"
+#~ "\n"
+#~ "Select your printer from the list below:"
+#~ msgstr ""
+#~ "Per stampare direttamente sulla stampante in rete, verificare che la stampante desiderata sia collegata alla rete mediante un cavo di rete o mediante collegamento alla rete WIFI. Se si collega Cura alla stampante, è comunque possibile utilizzare una chiavetta USB per trasferire i file codice G alla stampante.\n"
+#~ "\n"
+#~ "Selezionare la stampante dall’elenco seguente:"
+
+#~ msgctxt "@info"
+#~ msgid ""
+#~ "Please make sure your printer has a connection:\n"
+#~ "- Check if the printer is turned on.\n"
+#~ "- Check if the printer is connected to the network."
+#~ msgstr ""
+#~ "Accertarsi che la stampante sia collegata:\n"
+#~ "- Controllare se la stampante è accesa.\n"
+#~ "- Controllare se la stampante è collegata alla rete."
+
+#~ msgctxt "@option:check"
+#~ msgid "See only current build plate"
+#~ msgstr "Vedi solo il piano di stampa corrente"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange to all build plates"
+#~ msgstr "Sistema su tutti i piani di stampa"
+
+#~ msgctxt "@action:button"
+#~ msgid "Arrange current build plate"
+#~ msgstr "Sistema il piano di stampa corrente"
+
+#~ msgctxt "description"
+#~ msgid "Allows saving the resulting slice as an X3G file, to support printers that read this format (Malyan, Makerbot and other Sailfish-based printers)."
+#~ msgstr "Consente di salvare il sezionamento risultante come un file X3G, per supportare le stampanti che leggono questo formato (Malyan, Makerbot ed altre stampanti basate su firmware Sailfish)."
+
+#~ msgctxt "name"
+#~ msgid "X3GWriter"
+#~ msgstr "X3GWriter"
+
+#~ msgctxt "description"
+#~ msgid "Reads SVG files as toolpaths, for debugging printer movements."
+#~ msgstr "Legge i file SVG come toolpath (percorsi utensile), per eseguire il debug dei movimenti della stampante."
+
+#~ msgctxt "name"
+#~ msgid "SVG Toolpath Reader"
+#~ msgstr "Lettore di toolpath (percorso utensile) SVG"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Changelog"
+#~ msgstr "Registro modifiche"
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Show Changelog"
+#~ msgstr "Visualizza registro modifiche"
+
+#~ msgctxt "@info:status"
+#~ msgid "Sending data to remote cluster"
+#~ msgstr "Invio dati al cluster remoto"
+
+#~ msgctxt "@info:status"
+#~ msgid "Connect to Ultimaker Cloud"
+#~ msgstr "Collegato a Ultimaker Cloud"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymized usage statistics."
+#~ msgstr "Cura raccoglie statistiche di utilizzo in forma anonima."
+
+#~ msgctxt "@info:title"
+#~ msgid "Collecting Data"
+#~ msgstr "Acquisizione dati"
+
+#~ msgctxt "@action:button"
+#~ msgid "More info"
+#~ msgstr "Per saperne di più"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "See more information on what data Cura sends."
+#~ msgstr "Vedere ulteriori informazioni sui dati inviati da Cura."
+
+#~ msgctxt "@action:button"
+#~ msgid "Allow"
+#~ msgstr "Consenti"
+
+#~ msgctxt "@action:tooltip"
+#~ msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."
+#~ msgstr "Consente a Cura di inviare in forma anonima statistiche d’uso, riguardanti alcune delle preferenze e impostazioni, la versione cura e una serie di modelli in sezionamento, per aiutare a dare priorità a miglioramenti futuri in Cura."
+
+#~ msgctxt "@item:inmenu"
+#~ msgid "Evaluation"
+#~ msgstr "Valutazione"
+
+#~ msgctxt "@info:title"
+#~ msgid "Network enabled printers"
+#~ msgstr "Stampanti abilitate per la rete"
+
+#~ msgctxt "@info:title"
+#~ msgid "Local printers"
+#~ msgstr "Stampanti locali"
+
+#~ msgctxt "@info:backup_failed"
+#~ msgid "Tried to restore a Cura backup that does not match your current version."
+#~ msgstr "Tentativo di ripristinare un backup di Cura non corrispondente alla versione corrente."
+
+#~ msgctxt "@title"
+#~ msgid "Machine Settings"
+#~ msgstr "Impostazioni macchina"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Settings"
+#~ msgstr "Impostazioni della stampante"
+
+#~ msgctxt "@option:check"
+#~ msgid "Origin at center"
+#~ msgstr "Origine al centro"
+
+#~ msgctxt "@option:check"
+#~ msgid "Heated bed"
+#~ msgstr "Piano riscaldato"
+
+#~ msgctxt "@label"
+#~ msgid "Printhead Settings"
+#~ msgstr "Impostazioni della testina di stampa"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distanza tra il lato sinistro della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distanza tra il lato anteriore della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distanza tra il lato destro della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\"."
+#~ msgstr "Distanza tra il lato posteriore della testina di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testina di stampa durante la stampa \"Uno alla volta\"."
+
+#~ msgctxt "@label"
+#~ msgid "Gantry height"
+#~ msgstr "Altezza gantry"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\"."
+#~ msgstr "La differenza di altezza tra la punta dell’ugello e il sistema gantry (assi X e Y). Utilizzata per evitare collisioni tra le stampe precedenti e il gantry durante la stampa \"Uno alla volta\"."
+
+#~ msgctxt "@label"
+#~ msgid "Start G-code"
+#~ msgstr "Codice G avvio"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very start."
+#~ msgstr "Comandi codice G da eseguire all’avvio."
+
+#~ msgctxt "@label"
+#~ msgid "End G-code"
+#~ msgstr "Codice G fine"
+
+#~ msgctxt "@tooltip"
+#~ msgid "G-code commands to be executed at the very end."
+#~ msgstr "Comandi codice G da eseguire alla fine."
+
+#~ msgctxt "@label"
+#~ msgid "Nozzle Settings"
+#~ msgstr "Impostazioni ugello"
+
+#~ msgctxt "@tooltip"
+#~ msgid "The nominal diameter of filament supported by the printer. The exact diameter will be overridden by the material and/or the profile."
+#~ msgstr "Diametro nominale del filamento supportato dalla stampante. Il diametro esatto verrà sovrapposto dal materiale e/o dal profilo."
+
+#~ msgctxt "@label"
+#~ msgid "Extruder Start G-code"
+#~ msgstr "Codice G avvio estrusore"
+
+#~ msgctxt "@label"
+#~ msgid "Extruder End G-code"
+#~ msgstr "Codice G fine estrusore"
+
+#~ msgctxt "@label"
+#~ msgid "Changelog"
+#~ msgstr "Registro modifiche"
+
+#~ msgctxt "@title:window"
+#~ msgid "User Agreement"
+#~ msgstr "Contratto di licenza"
+
+#~ msgctxt "@alabel"
+#~ msgid "Enter the IP address or hostname of your printer on the network."
+#~ msgstr "Inserire l’indirizzo IP o l’hostname della stampante sulla rete."
+
+#~ msgctxt "@info"
+#~ msgid "Please select a network connected printer to monitor."
+#~ msgstr "Selezionare una stampante collegata alla rete per controllare."
+
+#~ msgctxt "@info"
+#~ msgid "Please connect your Ultimaker printer to your local network."
+#~ msgstr "Collegare la stampante Ultimaker alla rete locale."
+
+#~ msgctxt "@text:window"
+#~ msgid "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent."
+#~ msgstr "Cura invia dati anonimi ad Ultimaker per migliorare la qualità di stampa e l'esperienza dell'utente. Di seguito è riportato un esempio dei dati inviati."
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send this data"
+#~ msgstr "Non desidero inviare questi dati"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending this data to Ultimaker and help us improve Cura"
+#~ msgstr "Consenti l’invio di questi dati ad Ultimaker e aiutaci ad ottimizzare Cura"
+
+#~ msgctxt "@label"
+#~ msgid "No print selected"
+#~ msgstr "Nessuna stampante selezionata"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh."
+#~ msgstr "Per impostazione predefinita, i pixel bianchi rappresentano i punti alti sulla griglia, mentre i pixel neri rappresentano i punti bassi sulla griglia. Modificare questa opzione per invertire la situazione in modo tale che i pixel neri rappresentino i punti alti sulla griglia e i pixel bianchi rappresentino i punti bassi."
+
+#~ msgctxt "@title"
+#~ msgid "Select Printer Upgrades"
+#~ msgstr "Seleziona gli aggiornamenti della stampante"
+
+#~ msgctxt "@label"
+#~ msgid "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."
+#~ msgstr "Seleziona l’estrusore da utilizzare per la stampa di strutture di supporto. Ciò consentirà di costruire strutture di supporto sotto il modello per evitare cedimenti del modello o di stampare a mezz'aria."
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile"
+#~ msgstr "Questo profilo di qualità non è disponibile per il materiale e la configurazione ugello corrente. Modificarli per abilitare questo profilo di qualità"
+
+#~ msgctxt "@label shown when we load a Gcode file"
+#~ msgid "Print setup disabled. G code file can not be modified."
+#~ msgstr "Impostazione di stampa disabilitata. Impossibile modificare il file codice G."
+
+#~ msgctxt "@label"
+#~ msgid "See the material compatibility chart"
+#~ msgstr "Vedere il grafico di compatibilità dei materiali"
+
+#~ msgctxt "@label"
+#~ msgid "View types"
+#~ msgstr "Visualizza tipi"
+
+#~ msgctxt "@label"
+#~ msgid "Hi "
+#~ msgstr "Ciao "
+
+#~ msgctxt "@text"
+#~ msgid ""
+#~ "- Send print jobs to Ultimaker printers outside your local network\n"
+#~ "- Store your Ultimaker Cura settings in the cloud for use anywhere\n"
+#~ "- Get exclusive access to material profiles from leading brands"
+#~ msgstr ""
+#~ "- Invia i processi di stampa alle stampanti Ultimaker esterne alla rete locale\n"
+#~ "- Invia le impostazioni Ultimaker Cura nel cloud per usarle ovunque\n"
+#~ "- Ottieni l’accesso esclusivo ai profili materiale da marchi leader"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Unable to Slice"
+#~ msgstr "Sezionamento impossibile"
+
+#~ msgctxt "@label"
+#~ msgid "Time specification"
+#~ msgstr "Indicazioni di tempo"
+
+#~ msgctxt "@label"
+#~ msgid "Material specification"
+#~ msgstr "Specifiche materiale"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Add a printer to Cura"
+#~ msgstr "Aggiungi una stampante a Cura"
+
+#~ msgctxt "@title:tab"
+#~ msgid ""
+#~ "Select the printer you want to use from the list below.\n"
+#~ "\n"
+#~ "If your printer is not in the list, use the \"Custom FFF Printer\" from the \"Custom\" category and adjust the settings to match your printer in the next dialog."
+#~ msgstr ""
+#~ "Seleziona la stampante da usare dell’elenco seguente.\n"
+#~ "\n"
+#~ "Se la stampante non è nell’elenco, usare la “Stampante FFF personalizzata\" dalla categoria “Personalizzata\" e regolare le impostazioni in modo che corrispondano alla stampante nella finestra di dialogo successiva."
+
+#~ msgctxt "@label"
+#~ msgid "Manufacturer"
+#~ msgstr "Produttore"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name"
+#~ msgstr "Nome stampante"
+
+#~ msgctxt "@action:button"
+#~ msgid "Add Printer"
+#~ msgstr "Aggiungi stampante"
#~ msgid "Modify G-Code"
#~ msgstr "Modifica G-code"
@@ -5328,62 +6476,6 @@ msgstr "X3GWriter"
#~ msgid "Click to check the material compatibility on Ultimaker.com."
#~ msgstr "Fai clic per verificare la compatibilità del materiale su Ultimaker.com."
-#~ msgctxt "description"
-#~ msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
-#~ msgstr "Fornisce un modo per modificare le impostazioni della macchina (come il volume di stampa, la dimensione ugello, ecc.)"
-
-#~ msgctxt "name"
-#~ msgid "Machine Settings action"
-#~ msgstr "Azione Impostazioni macchina"
-
-#~ msgctxt "description"
-#~ msgid "Find, manage and install new Cura packages."
-#~ msgstr "Trova, gestisce ed installa nuovi pacchetti Cura."
-
-#~ msgctxt "name"
-#~ msgid "Toolbox"
-#~ msgstr "Casella degli strumenti"
-
-#~ msgctxt "description"
-#~ msgid "Provides the X-Ray view."
-#~ msgstr "Fornisce la vista a raggi X."
-
-#~ msgctxt "name"
-#~ msgid "X-Ray View"
-#~ msgstr "Vista ai raggi X"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading X3D files."
-#~ msgstr "Fornisce il supporto per la lettura di file X3D."
-
-#~ msgctxt "name"
-#~ msgid "X3D Reader"
-#~ msgstr "Lettore X3D"
-
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a file."
-#~ msgstr "Scrive il codice G in un file."
-
-#~ msgctxt "name"
-#~ msgid "G-code Writer"
-#~ msgstr "Writer codice G"
-
-#~ msgctxt "description"
-#~ msgid "Checks models and print configuration for possible printing issues and give suggestions."
-#~ msgstr "Controlla i modelli e la configurazione di stampa per eventuali problematiche di stampa e suggerimenti."
-
-#~ msgctxt "name"
-#~ msgid "Model Checker"
-#~ msgstr "Controllo modello"
-
-#~ msgctxt "description"
-#~ msgid "Dump the contents of all settings to a HTML file."
-#~ msgstr "Scarica contenuto di tutte le impostazioni in un file HTML."
-
-#~ msgctxt "name"
-#~ msgid "God Mode"
-#~ msgstr "Modalità God"
-
#~ msgctxt "description"
#~ msgid "Shows changes since latest checked version."
#~ msgstr "Mostra le modifiche dall'ultima versione selezionata."
@@ -5392,14 +6484,6 @@ msgstr "X3GWriter"
#~ msgid "Changelog"
#~ msgstr "Registro modifiche"
-#~ msgctxt "description"
-#~ msgid "Provides a machine actions for updating firmware."
-#~ msgstr "Fornisce azioni macchina per l’aggiornamento del firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Updater"
-#~ msgstr "Aggiornamento firmware"
-
#~ msgctxt "description"
#~ msgid "Create a flattend quality changes profile."
#~ msgstr "Crea un profilo appiattito."
@@ -5408,14 +6492,6 @@ msgstr "X3GWriter"
#~ msgid "Profile flatener"
#~ msgstr "Appiattitore di profilo"
-#~ msgctxt "description"
-#~ msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware."
-#~ msgstr "Accetta i G-Code e li invia ad una stampante. I plugin possono anche aggiornare il firmware."
-
-#~ msgctxt "name"
-#~ msgid "USB printing"
-#~ msgstr "Stampa USB"
-
#~ msgctxt "description"
#~ msgid "Ask the user once if he/she agrees with our license."
#~ msgstr "Chiedere una volta all'utente se accetta la nostra licenza."
@@ -5424,278 +6500,6 @@ msgstr "X3GWriter"
#~ msgid "UserAgreement"
#~ msgstr "Contratto di licenza"
-#~ msgctxt "description"
-#~ msgid "Writes g-code to a compressed archive."
-#~ msgstr "Scrive il codice G in un archivio compresso."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Writer"
-#~ msgstr "Writer codice G compresso"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing Ultimaker Format Packages."
-#~ msgstr "Fornisce il supporto per la scrittura di pacchetti formato Ultimaker."
-
-#~ msgctxt "name"
-#~ msgid "UFP Writer"
-#~ msgstr "Writer UFP"
-
-#~ msgctxt "description"
-#~ msgid "Provides a prepare stage in Cura."
-#~ msgstr "Fornisce una fase di preparazione in Cura."
-
-#~ msgctxt "name"
-#~ msgid "Prepare Stage"
-#~ msgstr "Fase di preparazione"
-
-#~ msgctxt "description"
-#~ msgid "Provides removable drive hotplugging and writing support."
-#~ msgstr "Fornisce il collegamento a caldo dell'unità rimovibile e il supporto per la scrittura."
-
-#~ msgctxt "name"
-#~ msgid "Removable Drive Output Device Plugin"
-#~ msgstr "Plugin dispositivo di output unità rimovibile"
-
-#~ msgctxt "description"
-#~ msgid "Manages network connections to Ultimaker 3 printers."
-#~ msgstr "Gestisce le connessioni di rete alle stampanti Ultimaker 3."
-
-#~ msgctxt "name"
-#~ msgid "UM3 Network Connection"
-#~ msgstr "Connessione di rete UM3"
-
-#~ msgctxt "description"
-#~ msgid "Provides a monitor stage in Cura."
-#~ msgstr "Fornisce una fase di controllo in Cura."
-
-#~ msgctxt "name"
-#~ msgid "Monitor Stage"
-#~ msgstr "Fase di controllo"
-
-#~ msgctxt "description"
-#~ msgid "Checks for firmware updates."
-#~ msgstr "Controlla disponibilità di aggiornamenti firmware."
-
-#~ msgctxt "name"
-#~ msgid "Firmware Update Checker"
-#~ msgstr "Controllo aggiornamento firmware"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Simulation view."
-#~ msgstr "Fornisce la vista di simulazione."
-
-#~ msgctxt "name"
-#~ msgid "Simulation View"
-#~ msgstr "Vista simulazione"
-
-#~ msgctxt "description"
-#~ msgid "Reads g-code from a compressed archive."
-#~ msgstr "Legge il codice G da un archivio compresso."
-
-#~ msgctxt "name"
-#~ msgid "Compressed G-code Reader"
-#~ msgstr "Lettore codice G compresso"
-
-#~ msgctxt "description"
-#~ msgid "Extension that allows for user created scripts for post processing"
-#~ msgstr "Estensione che consente la post-elaborazione degli script creati da utente"
-
-#~ msgctxt "name"
-#~ msgid "Post Processing"
-#~ msgstr "Post-elaborazione"
-
-#~ msgctxt "description"
-#~ msgid "Creates an eraser mesh to block the printing of support in certain places"
-#~ msgstr "Crea una maglia di cancellazione per bloccare la stampa del supporto in alcune posizioni"
-
-#~ msgctxt "name"
-#~ msgid "Support Eraser"
-#~ msgstr "Cancellazione supporto"
-
-#~ msgctxt "description"
-#~ msgid "Submits anonymous slice info. Can be disabled through preferences."
-#~ msgstr "Invia informazioni su sezionamento anonime Può essere disabilitato tramite le preferenze."
-
-#~ msgctxt "name"
-#~ msgid "Slice info"
-#~ msgstr "Informazioni su sezionamento"
-
-#~ msgctxt "description"
-#~ msgid "Provides capabilities to read and write XML-based material profiles."
-#~ msgstr "Offre la possibilità di leggere e scrivere profili di materiali basati su XML."
-
-#~ msgctxt "name"
-#~ msgid "Material Profiles"
-#~ msgstr "Profili del materiale"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from legacy Cura versions."
-#~ msgstr "Fornisce supporto per l'importazione di profili dalle versioni legacy Cura."
-
-#~ msgctxt "name"
-#~ msgid "Legacy Cura Profile Reader"
-#~ msgstr "Lettore legacy profilo Cura"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing profiles from g-code files."
-#~ msgstr "Fornisce supporto per l'importazione di profili da file G-Code."
-
-#~ msgctxt "name"
-#~ msgid "G-code Profile Reader"
-#~ msgstr "Lettore profilo codice G"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.2 to Cura 3.3."
-#~ msgstr "Aggiorna le configurazioni da Cura 3.2 a Cura 3.3."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.2 to 3.3"
-#~ msgstr "Aggiornamento della versione da 3.2 a 3.3"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.3 to Cura 3.4."
-#~ msgstr "Aggiorna le configurazioni da Cura 3.3 a Cura 3.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.3 to 3.4"
-#~ msgstr "Aggiornamento della versione da 3.3 a 3.4"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.5 to Cura 2.6."
-#~ msgstr "Aggiorna le configurazioni da Cura 2.5 a Cura 2.6."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.5 to 2.6"
-#~ msgstr "Aggiornamento della versione da 2.5 a 2.6"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.7 to Cura 3.0."
-#~ msgstr "Aggiorna le configurazioni da Cura 2.7 a Cura 3.0."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.7 to 3.0"
-#~ msgstr "Aggiornamento della versione da 2.7 a 3.0"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.4 to Cura 3.5."
-#~ msgstr "Aggiorna le configurazioni da Cura 3.4 a Cura 3.5."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.4 to 3.5"
-#~ msgstr "Aggiornamento della versione da 3.4 a 3.5"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 3.0 to Cura 3.1."
-#~ msgstr "Aggiorna le configurazioni da Cura 3.0 a Cura 3.1."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 3.0 to 3.1"
-#~ msgstr "Aggiornamento della versione da 3.0 a 3.1"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.6 to Cura 2.7."
-#~ msgstr "Aggiorna le configurazioni da Cura 2.6 a Cura 2.7."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.6 to 2.7"
-#~ msgstr "Aggiornamento della versione da 2.6 a 2.7"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.1 to Cura 2.2."
-#~ msgstr "Aggiorna le configurazioni da Cura 2.1 a Cura 2.2."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.1 to 2.2"
-#~ msgstr "Aggiornamento della versione da 2.1 a 2.2"
-
-#~ msgctxt "description"
-#~ msgid "Upgrades configurations from Cura 2.2 to Cura 2.4."
-#~ msgstr "Aggiorna le configurazioni da Cura 2.2 a Cura 2.4."
-
-#~ msgctxt "name"
-#~ msgid "Version Upgrade 2.2 to 2.4"
-#~ msgstr "Aggiornamento della versione da 2.2 a 2.4"
-
-#~ msgctxt "description"
-#~ msgid "Enables ability to generate printable geometry from 2D image files."
-#~ msgstr "Abilita la possibilità di generare geometria stampabile da file immagine 2D."
-
-#~ msgctxt "name"
-#~ msgid "Image Reader"
-#~ msgstr "Lettore di immagine"
-
-#~ msgctxt "description"
-#~ msgid "Provides the link to the CuraEngine slicing backend."
-#~ msgstr "Fornisce il collegamento al back-end di sezionamento CuraEngine."
-
-#~ msgctxt "name"
-#~ msgid "CuraEngine Backend"
-#~ msgstr "Back-end CuraEngine"
-
-#~ msgctxt "description"
-#~ msgid "Provides the Per Model Settings."
-#~ msgstr "Fornisce le impostazioni per modello."
-
-#~ msgctxt "name"
-#~ msgid "Per Model Settings Tool"
-#~ msgstr "Utilità impostazioni per modello"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for reading 3MF files."
-#~ msgstr "Fornisce il supporto per la lettura di file 3MF."
-
-#~ msgctxt "name"
-#~ msgid "3MF Reader"
-#~ msgstr "Lettore 3MF"
-
-#~ msgctxt "description"
-#~ msgid "Provides a normal solid mesh view."
-#~ msgstr "Fornisce una normale visualizzazione a griglia compatta."
-
-#~ msgctxt "name"
-#~ msgid "Solid View"
-#~ msgstr "Visualizzazione compatta"
-
-#~ msgctxt "description"
-#~ msgid "Allows loading and displaying G-code files."
-#~ msgstr "Consente il caricamento e la visualizzazione dei file codice G."
-
-#~ msgctxt "name"
-#~ msgid "G-code Reader"
-#~ msgstr "Lettore codice G"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for exporting Cura profiles."
-#~ msgstr "Fornisce supporto per l'esportazione dei profili Cura."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Writer"
-#~ msgstr "Writer profilo Cura"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for writing 3MF files."
-#~ msgstr "Fornisce il supporto per la scrittura di file 3MF."
-
-#~ msgctxt "name"
-#~ msgid "3MF Writer"
-#~ msgstr "Writer 3MF"
-
-#~ msgctxt "description"
-#~ msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.)."
-#~ msgstr "Fornisce azioni macchina per le macchine Ultimaker (come la procedura guidata di livellamento del piano di stampa, la selezione degli aggiornamenti, ecc.)"
-
-#~ msgctxt "name"
-#~ msgid "Ultimaker machine actions"
-#~ msgstr "Azioni della macchina Ultimaker"
-
-#~ msgctxt "description"
-#~ msgid "Provides support for importing Cura profiles."
-#~ msgstr "Fornisce supporto per l'importazione dei profili Cura."
-
-#~ msgctxt "name"
-#~ msgid "Cura Profile Reader"
-#~ msgstr "Lettore profilo Cura"
-
#~ msgctxt "@warning:status"
#~ msgid "Please generate G-code before saving."
#~ msgstr "Generare il codice G prima di salvare."
@@ -5736,14 +6540,6 @@ msgstr "X3GWriter"
#~ msgid "Upgrade Firmware"
#~ msgstr "Aggiorna firmware"
-#~ msgctxt "description"
-#~ msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
-#~ msgstr "Consente ai produttori di materiali di creare nuovi profili materiale e di qualità utilizzando una UI drop-in."
-
-#~ msgctxt "name"
-#~ msgid "Print Profile Assistant"
-#~ msgstr "Assistente profilo di stampa"
-
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Stampa con Doodle3D WiFi-Box"
diff --git a/resources/i18n/it_IT/fdmextruder.def.json.po b/resources/i18n/it_IT/fdmextruder.def.json.po
index 355986a0dd..4d730ebf7c 100644
--- a/resources/i18n/it_IT/fdmextruder.def.json.po
+++ b/resources/i18n/it_IT/fdmextruder.def.json.po
@@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Italian\n"
"Language: it_IT\n"
@@ -84,7 +84,7 @@ msgstr "Codice G avvio estrusore"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
msgid "Start g-code to execute when switching to this extruder."
-msgstr ""
+msgstr "Inizio codice G da eseguire quando si passa a questo estrusore."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -124,7 +124,7 @@ msgstr "Codice G fine estrusore"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
msgid "End g-code to execute when switching away from this extruder."
-msgstr ""
+msgstr "Fine codice G da eseguire quando si passa a questo estrusore."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
diff --git a/resources/i18n/it_IT/fdmprinter.def.json.po b/resources/i18n/it_IT/fdmprinter.def.json.po
index 7cb8244362..2f7a93df43 100644
--- a/resources/i18n/it_IT/fdmprinter.def.json.po
+++ b/resources/i18n/it_IT/fdmprinter.def.json.po
@@ -5,12 +5,12 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0000\n"
-"PO-Revision-Date: 2018-09-28 15:02+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Italian\n"
+"POT-Creation-Date: 2019-11-05 13:13+0000\n"
+"PO-Revision-Date: 2019-07-29 15:51+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: Italian , Italian \n"
"Language: it_IT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -215,6 +215,16 @@ msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
msgstr "Indica se la macchina ha un piano di stampa riscaldato."
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume label"
+msgid "Has Build Volume Temperature Stabilization"
+msgstr "È dotato della stabilizzazione della temperatura del volume di stampa"
+
+#: fdmprinter.def.json
+msgctxt "machine_heated_build_volume description"
+msgid "Whether the machine is able to stabilize the build volume temperature."
+msgstr "Se la macchina è in grado di stabilizzare la temperatura del volume di stampa."
+
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
@@ -237,7 +247,7 @@ msgstr "Il numero di treni di estrusori. Un treno di estrusori è la combinazion
#: fdmprinter.def.json
msgctxt "extruders_enabled_count label"
-msgid "Number of Extruders that are enabled"
+msgid "Number of Extruders That Are Enabled"
msgstr "Numero di estrusori abilitati"
#: fdmprinter.def.json
@@ -247,7 +257,7 @@ msgstr "Numero di treni di estrusori abilitati; impostato automaticamente nel so
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
-msgid "Outer nozzle diameter"
+msgid "Outer Nozzle Diameter"
msgstr "Diametro esterno ugello"
#: fdmprinter.def.json
@@ -257,7 +267,7 @@ msgstr "Il diametro esterno della punta dell'ugello."
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
+msgid "Nozzle Length"
msgstr "Lunghezza ugello"
#: fdmprinter.def.json
@@ -267,7 +277,7 @@ msgstr "La differenza di altezza tra la punta dell’ugello e la parte inferiore
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
+msgid "Nozzle Angle"
msgstr "Angolo ugello"
#: fdmprinter.def.json
@@ -277,7 +287,7 @@ msgstr "L’angolo tra il piano orizzontale e la parte conica esattamente sopra
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length label"
-msgid "Heat zone length"
+msgid "Heat Zone Length"
msgstr "Lunghezza della zona di riscaldamento"
#: fdmprinter.def.json
@@ -307,7 +317,7 @@ msgstr "Per controllare la temperatura da Cura. Disattivare per controllare la t
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed label"
-msgid "Heat up speed"
+msgid "Heat Up Speed"
msgstr "Velocità di riscaldamento"
#: fdmprinter.def.json
@@ -317,7 +327,7 @@ msgstr "La velocità (°C/s) alla quale l’ugello si riscalda calcolando la med
#: fdmprinter.def.json
msgctxt "machine_nozzle_cool_down_speed label"
-msgid "Cool down speed"
+msgid "Cool Down Speed"
msgstr "Velocità di raffreddamento"
#: fdmprinter.def.json
@@ -337,8 +347,8 @@ msgstr "Il tempo minimo in cui un estrusore deve essere inattivo prima che l’u
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
-msgstr "Tipo di codice G"
+msgid "G-code Flavor"
+msgstr "Versione codice G"
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor description"
@@ -402,7 +412,7 @@ msgstr "Specifica se usare comandi di retrazione firmware (G10/G11) anziché uti
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
+msgid "Disallowed Areas"
msgstr "Aree non consentite"
#: fdmprinter.def.json
@@ -422,7 +432,7 @@ msgstr "Un elenco di poligoni con aree alle quali l’ugello non può accedere."
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
+msgid "Machine Head Polygon"
msgstr "Poligono testina macchina"
#: fdmprinter.def.json
@@ -432,7 +442,7 @@ msgstr "Una silhouette 2D della testina di stampa (cappucci ventola esclusi)."
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
-msgid "Machine head & Fan polygon"
+msgid "Machine Head & Fan Polygon"
msgstr "Poligono testina macchina e ventola"
#: fdmprinter.def.json
@@ -442,7 +452,7 @@ msgstr "Una silhouette 2D della testina di stampa (cappucci ventola inclusi)."
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Altezza gantry"
#: fdmprinter.def.json
@@ -472,7 +482,7 @@ msgstr "Il diametro interno dell’ugello. Modificare questa impostazione quando
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label"
-msgid "Offset With Extruder"
+msgid "Offset with Extruder"
msgstr "Offset con estrusore"
#: fdmprinter.def.json
@@ -1020,6 +1030,17 @@ msgctxt "bottom_layers description"
msgid "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number."
msgstr "Indica il numero degli strati inferiori. Quando calcolato mediante lo spessore dello strato inferiore, il valore viene arrotondato a numero intero."
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers label"
+msgid "Initial Bottom Layers"
+msgstr "Layer inferiori iniziali"
+
+#: fdmprinter.def.json
+msgctxt "initial_bottom_layers description"
+msgid "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number."
+msgstr "Il numero di layer inferiori iniziali, dal piano di stampa verso l'alto. Quando viene calcolato mediante lo spessore inferiore, questo valore viene arrotondato"
+" a un numero intero."
+
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
@@ -1270,6 +1291,56 @@ msgctxt "z_seam_type option sharpest_corner"
msgid "Sharpest Corner"
msgstr "Angolo più acuto"
+#: fdmprinter.def.json
+msgctxt "z_seam_position label"
+msgid "Z Seam Position"
+msgstr "Posizione della cucitura in Z"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position description"
+msgid "The position near where to start printing each part in a layer."
+msgstr "La posizione accanto al punto in cui avviare la stampa di ciascuna parte in uno layer."
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backleft"
+msgid "Back Left"
+msgstr "Indietro a sinistra"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option back"
+msgid "Back"
+msgstr "Indietro"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option backright"
+msgid "Back Right"
+msgstr "Indietro a destra"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option right"
+msgid "Right"
+msgstr "Destra"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontright"
+msgid "Front Right"
+msgstr "Avanti a destra"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option front"
+msgid "Front"
+msgstr "Avanti"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option frontleft"
+msgid "Front Left"
+msgstr "Avanti a sinistra"
+
+#: fdmprinter.def.json
+msgctxt "z_seam_position option left"
+msgid "Left"
+msgstr "Sinistra"
+
#: fdmprinter.def.json
msgctxt "z_seam_x label"
msgid "Z Seam X"
@@ -1297,8 +1368,8 @@ msgstr "Preferenze angolo giunzione"
#: fdmprinter.def.json
msgctxt "z_seam_corner description"
-msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
-msgstr "Controlla se gli angoli sul profilo del modello influenzano la posizione della giunzione. Nessuno significa che gli angoli non hanno alcuna influenza sulla posizione della giunzione. Nascondi giunzione favorisce la presenza della giunzione su un angolo interno. Esponi giunzione favorisce la presenza della giunzione su un angolo esterno. Nascondi o esponi giunzione favorisce la presenza della giunzione su un angolo interno o esterno."
+msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner. Smart Hiding allows both inside and outside corners, but chooses inside corners more frequently, if appropriate."
+msgstr "Controlla se gli angoli sul profilo del modello influenzano la posizione della giunzione. Nessuno significa che gli angoli non hanno alcuna influenza sulla posizione della giunzione. Nascondi giunzione favorisce la presenza della giunzione su un angolo interno. Esponi giunzione favorisce la presenza della giunzione su un angolo esterno. Nascondi o esponi giunzione favorisce la presenza della giunzione su un angolo interno o esterno. Smart Hiding consente sia gli angoli interni che quelli esterni ma sceglie con maggiore frequenza gli angoli interni, se opportuno."
#: fdmprinter.def.json
msgctxt "z_seam_corner option z_seam_corner_none"
@@ -1320,6 +1391,11 @@ msgctxt "z_seam_corner option z_seam_corner_any"
msgid "Hide or Expose Seam"
msgstr "Nascondi o esponi giunzione"
+#: fdmprinter.def.json
+msgctxt "z_seam_corner option z_seam_corner_weighted"
+msgid "Smart Hiding"
+msgstr "Occultamento intelligente"
+
#: fdmprinter.def.json
msgctxt "z_seam_relative label"
msgid "Z Seam Relative"
@@ -1332,13 +1408,13 @@ msgstr "Se abilitato, le coordinate della giunzione Z sono riferite al centro di
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic label"
-msgid "Ignore Small Z Gaps"
-msgstr "Ignora i piccoli interstizi a Z"
+msgid "No Skin in Z Gaps"
+msgstr "Nessun rivest. est. negli interstizi a Z"
#: fdmprinter.def.json
msgctxt "skin_no_small_gaps_heuristic description"
-msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
-msgstr "Quando il modello presenta piccoli spazi vuoti verticali, circa il 5% del tempo di calcolo supplementare può essere utilizzato per la generazione di rivestimenti esterni superiori ed inferiori in questi interstizi. In questo caso disabilitare l’impostazione."
+msgid "When the model has small vertical gaps of only a few layers, there should normally be skin around those layers in the narrow space. Enable this setting to not generate skin if the vertical gap is very small. This improves printing time and slicing time, but technically leaves infill exposed to the air."
+msgstr "Quando il modello presenta piccoli spazi vuoti verticali composti da un numero ridotto di strati, intorno a questi strati di norma dovrebbe essere presente un rivestimento esterno nell'interstizio. Abilitare questa impostazione per non generare il rivestimento esterno se l'interstizio verticale è molto piccolo. Ciò consente di migliorare il tempo di stampa e il tempo di sezionamento, ma dal punto di vista tecnico lascia il riempimento esposto all'aria."
#: fdmprinter.def.json
msgctxt "skin_outline_count label"
@@ -1357,8 +1433,8 @@ msgstr "Abilita stiratura"
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
-msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
-msgstr "Ulteriore passaggio sopra la superficie superiore, senza estrusione di materiale. Ha lo scopo di fondere ulteriormente la plastica alla sommità, creando una superficie più uniforme."
+msgid "Go over the top surface one additional time, but this time extruding very little material. This is meant to melt the plastic on top further, creating a smoother surface. The pressure in the nozzle chamber is kept high so that the creases in the surface are filled with material."
+msgstr "Andare ancora una volta sulla superficie superiore, questa volta estrudendo una piccolissima quantità di materiale. Lo scopo è quello di sciogliere ulteriormente la plastica sulla parte superiore, creando una superficie più liscia. La pressione nella camera dell'ugello viene mantenuta elevata, in modo che le grinze nella superficie siano riempite con il materiale."
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
@@ -1450,6 +1526,26 @@ msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
msgstr "Indica la variazione della velocità istantanea massima durante la stiratura."
+#: fdmprinter.def.json
+msgctxt "skin_overlap label"
+msgid "Skin Overlap Percentage"
+msgstr "Percentuale di sovrapposizione del rivestimento esterno"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Regolare l’entità della sovrapposizione tra le pareti e (i punti finali delle) linee centrali del rivestimento esterno espressa in percentuale delle larghezze delle linee del rivestimento esterno. Una leggera sovrapposizione consente alle pareti di essere saldamente collegate al rivestimento. Si noti che, data una larghezza uguale del rivestimento esterno e della linea perimetrale, qualsiasi percentuale superiore al 50% può già causare il superamento della parete da parte del rivestimento esterno in quanto, in quel punto, la posizione dell’ugello dell’estrusore del rivestimento esterno può già avere superato la parte centrale della parete."
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm label"
+msgid "Skin Overlap"
+msgstr "Sovrapposizione del rivestimento esterno"
+
+#: fdmprinter.def.json
+msgctxt "skin_overlap_mm description"
+msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
+msgstr "Regolare l’entità della sovrapposizione tra le pareti e (i punti finali delle) linee centrali del rivestimento esterno. Una leggera sovrapposizione consente alle pareti di essere saldamente collegate al rivestimento. Si noti che, data una larghezza uguale del rivestimento esterno e della linea perimetrale, qualsiasi percentuale superiore alla metà della parete può già causare il superamento della parete da parte del rivestimento esterno in quanto, in quel punto, la posizione dell’ugello dell’estrusore del rivestimento esterno può già aver superato la parte centrale della parete."
+
#: fdmprinter.def.json
msgctxt "infill label"
msgid "Infill"
@@ -1615,6 +1711,16 @@ msgctxt "infill_offset_y description"
msgid "The infill pattern is moved this distance along the Y axis."
msgstr "Il riempimento si sposta di questa distanza lungo l'asse Y."
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location label"
+msgid "Randomize Infill Start"
+msgstr "Avvio con riempimento casuale"
+
+#: fdmprinter.def.json
+msgctxt "infill_randomize_start_location description"
+msgid "Randomize which infill line is printed first. This prevents one segment becoming the strongest, but it does so at the cost of an additional travel move."
+msgstr "Decidere in modo casuale quale sarà la linea di riempimento ad essere stampata per prima. In tal modo si evita che un segmento diventi il più resistente sebbene si esegua uno spostamento aggiuntivo."
+
#: fdmprinter.def.json
msgctxt "infill_multiplier label"
msgid "Infill Line Multiplier"
@@ -1669,26 +1775,6 @@ msgctxt "infill_overlap_mm description"
msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
msgstr "Indica la quantità di sovrapposizione tra il riempimento e le pareti. Una leggera sovrapposizione consente il saldo collegamento delle pareti al riempimento."
-#: fdmprinter.def.json
-msgctxt "skin_overlap label"
-msgid "Skin Overlap Percentage"
-msgstr "Percentuale di sovrapposizione del rivestimento esterno"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm label"
-msgid "Skin Overlap"
-msgstr "Sovrapposizione del rivestimento esterno"
-
-#: fdmprinter.def.json
-msgctxt "skin_overlap_mm description"
-msgid "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "infill_wipe_dist label"
msgid "Infill Wipe Distance"
@@ -1869,6 +1955,16 @@ msgctxt "default_material_print_temperature description"
msgid "The default temperature used for printing. This should be the \"base\" temperature of a material. All other print temperatures should use offsets based on this value"
msgstr "La temperatura preimpostata utilizzata per la stampa. Deve essere la temperatura “base” di un materiale. Tutte le altre temperature di stampa devono usare scostamenti basati su questo valore"
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature label"
+msgid "Build Volume Temperature"
+msgstr "Temperatura volume di stampa"
+
+#: fdmprinter.def.json
+msgctxt "build_volume_temperature description"
+msgid "The temperature of the environment to print in. If this is 0, the build volume temperature will not be adjusted."
+msgstr "La temperatura dell'ambiente in cui stampare. Se il valore è 0, la temperatura del volume di stampa non verrà regolata."
+
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
msgid "Printing Temperature"
@@ -1979,6 +2075,86 @@ msgctxt "material_shrinkage_percentage description"
msgid "Shrinkage ratio in percentage."
msgstr "Il tasso di contrazione in percentuale."
+#: fdmprinter.def.json
+msgctxt "material_crystallinity label"
+msgid "Crystalline Material"
+msgstr "Materiale cristallino"
+
+#: fdmprinter.def.json
+msgctxt "material_crystallinity description"
+msgid "Is this material the type that breaks off cleanly when heated (crystalline), or is it the type that produces long intertwined polymer chains (non-crystalline)?"
+msgstr "Questo tipo di materiale è quello che si stacca in modo netto quando viene riscaldato (cristallino) oppure è il tipo che produce lunghe catene di polimeri intrecciati (non cristallino)?"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position label"
+msgid "Anti-ooze Retracted Position"
+msgstr "Posizione retratta anti fuoriuscita di materiale"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retracted_position description"
+msgid "How far the material needs to be retracted before it stops oozing."
+msgstr "La distanza alla quale deve essere retratto il materiale prima che smetta di fuoriuscire."
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed label"
+msgid "Anti-ooze Retraction Speed"
+msgstr "Velocità di retrazione anti fuoriuscita del materiale"
+
+#: fdmprinter.def.json
+msgctxt "material_anti_ooze_retraction_speed description"
+msgid "How fast the material needs to be retracted during a filament switch to prevent oozing."
+msgstr "La velocità a cui deve essere retratto il materiale durante un cambio di filamento per evitare la fuoriuscita di materiale."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position label"
+msgid "Break Preparation Retracted Position"
+msgstr "Posizione di retrazione prima della rottura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_retracted_position description"
+msgid "How far the filament can be stretched before it breaks, while heated."
+msgstr "La lunghezza massima di estensione del filamento prima che si rompa durante il riscaldamento."
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed label"
+msgid "Break Preparation Retraction Speed"
+msgstr "Velocità di retrazione prima della rottura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_preparation_speed description"
+msgid "How fast the filament needs to be retracted just before breaking it off in a retraction."
+msgstr "La velocità massima di retrazione del filamento prima che si rompa durante questa operazione."
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position label"
+msgid "Break Retracted Position"
+msgstr "Posizione di retrazione per la rottura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_retracted_position description"
+msgid "How far to retract the filament in order to break it cleanly."
+msgstr "La distanza di retrazione del filamento al fine di consentirne la rottura netta."
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed label"
+msgid "Break Retraction Speed"
+msgstr "Velocità di retrazione per la rottura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_speed description"
+msgid "The speed at which to retract the filament in order to break it cleanly."
+msgstr "La velocità alla quale retrarre il filamento al fine di romperlo in modo netto."
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature label"
+msgid "Break Temperature"
+msgstr "Temperatura di rottura"
+
+#: fdmprinter.def.json
+msgctxt "material_break_temperature description"
+msgid "The temperature at which the filament is broken for a clean break."
+msgstr "La temperatura a cui il filamento viene rotto, con una rottura netta."
+
#: fdmprinter.def.json
msgctxt "material_flow label"
msgid "Flow"
@@ -1989,6 +2165,126 @@ msgctxt "material_flow description"
msgid "Flow compensation: the amount of material extruded is multiplied by this value."
msgstr "Determina la compensazione del flusso: la quantità di materiale estruso viene moltiplicata per questo valore."
+#: fdmprinter.def.json
+msgctxt "wall_material_flow label"
+msgid "Wall Flow"
+msgstr "Flusso della parete"
+
+#: fdmprinter.def.json
+msgctxt "wall_material_flow description"
+msgid "Flow compensation on wall lines."
+msgstr "Compensazione del flusso sulle linee perimetrali."
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow label"
+msgid "Outer Wall Flow"
+msgstr "Flusso della parete esterna"
+
+#: fdmprinter.def.json
+msgctxt "wall_0_material_flow description"
+msgid "Flow compensation on the outermost wall line."
+msgstr "Compensazione del flusso sulla linea perimetrale più esterna."
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow label"
+msgid "Inner Wall(s) Flow"
+msgstr "Flusso pareti interne"
+
+#: fdmprinter.def.json
+msgctxt "wall_x_material_flow description"
+msgid "Flow compensation on wall lines for all wall lines except the outermost one."
+msgstr "Compensazione del flusso sulle linee perimetrali per tutte le linee perimetrali tranne quella più esterna."
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow label"
+msgid "Top/Bottom Flow"
+msgstr "Flusso superiore/inferiore"
+
+#: fdmprinter.def.json
+msgctxt "skin_material_flow description"
+msgid "Flow compensation on top/bottom lines."
+msgstr "Compensazione del flusso sulle linee superiore/inferiore."
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow label"
+msgid "Top Surface Skin Flow"
+msgstr "Flusso rivestimento esterno superficie superiore"
+
+#: fdmprinter.def.json
+msgctxt "roofing_material_flow description"
+msgid "Flow compensation on lines of the areas at the top of the print."
+msgstr "Compensazione del flusso sulle linee delle aree nella parte superiore della stampa."
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow label"
+msgid "Infill Flow"
+msgstr "Flusso di riempimento"
+
+#: fdmprinter.def.json
+msgctxt "infill_material_flow description"
+msgid "Flow compensation on infill lines."
+msgstr "Compensazione del flusso sulle linee di riempimento."
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow label"
+msgid "Skirt/Brim Flow"
+msgstr "Flusso dello skirt/brim"
+
+#: fdmprinter.def.json
+msgctxt "skirt_brim_material_flow description"
+msgid "Flow compensation on skirt or brim lines."
+msgstr "Compensazione del flusso sulle linee dello skirt o del brim."
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow label"
+msgid "Support Flow"
+msgstr "Flusso del supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_material_flow description"
+msgid "Flow compensation on support structure lines."
+msgstr "Compensazione del flusso sulle linee di supporto."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow label"
+msgid "Support Interface Flow"
+msgstr "Flusso interfaccia di supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_material_flow description"
+msgid "Flow compensation on lines of support roof or floor."
+msgstr "Compensazione del flusso sulle linee di supporto superiore o inferiore."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow label"
+msgid "Support Roof Flow"
+msgstr "Flusso supporto superiore"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_material_flow description"
+msgid "Flow compensation on support roof lines."
+msgstr "Compensazione del flusso sulle linee di supporto superiore."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow label"
+msgid "Support Floor Flow"
+msgstr "Flusso supporto inferiore"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_material_flow description"
+msgid "Flow compensation on support floor lines."
+msgstr "Compensazione del flusso sulle linee di supporto inferiore."
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow label"
+msgid "Prime Tower Flow"
+msgstr "Flusso torre di innesco"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_flow description"
+msgid "Flow compensation on prime tower lines."
+msgstr "Compensazione del flusso sulle linee della torre di innesco."
+
#: fdmprinter.def.json
msgctxt "material_flow_layer_0 label"
msgid "Initial Layer Flow"
@@ -2106,7 +2402,7 @@ msgstr "Limitazione delle retrazioni del supporto"
#: fdmprinter.def.json
msgctxt "limit_support_retractions description"
-msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure."
msgstr "Omettere la retrazione negli spostamenti da un supporto ad un altro in linea retta. L'abilitazione di questa impostazione riduce il tempo di stampa, ma può comportare un'eccessiva produzione di filamenti all'interno della struttura del supporto."
#: fdmprinter.def.json
@@ -2127,7 +2423,7 @@ msgstr "Distanza di retrazione cambio ugello"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
msgid "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr ""
+msgstr "Indica il valore di retrazione alla commutazione degli estrusori. Impostato a 0 per nessuna retrazione. Questo valore generalmente dovrebbe essere lo stesso della lunghezza della zona di riscaldamento."
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_speeds label"
@@ -2159,6 +2455,16 @@ msgctxt "switch_extruder_prime_speed description"
msgid "The speed at which the filament is pushed back after a nozzle switch retraction."
msgstr "Indica la velocità alla quale il filamento viene sospinto indietro dopo la retrazione per cambio ugello."
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount label"
+msgid "Nozzle Switch Extra Prime Amount"
+msgstr "Quantità di materiale extra della Prime Tower, al cambio ugello"
+
+#: fdmprinter.def.json
+msgctxt "switch_extruder_extra_prime_amount description"
+msgid "Extra material to prime after nozzle switching."
+msgstr "Materiale extra per l'innesco dopo il cambio dell'ugello."
+
#: fdmprinter.def.json
msgctxt "speed label"
msgid "Speed"
@@ -2350,14 +2656,14 @@ msgid "The speed at which the skirt and brim are printed. Normally this is done
msgstr "Indica la velocità a cui sono stampati lo skirt ed il brim. Normalmente questa operazione viene svolta alla velocità di stampa dello strato iniziale, ma a volte è possibile che si desideri stampare lo skirt o il brim ad una velocità diversa."
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override label"
-msgid "Maximum Z Speed"
-msgstr "Velocità massima Z"
+msgctxt "speed_z_hop label"
+msgid "Z Hop Speed"
+msgstr "Velocità di sollevamento Z"
#: fdmprinter.def.json
-msgctxt "max_feedrate_z_override description"
-msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
-msgstr "Indica la velocità massima di spostamento del piano di stampa. L’impostazione di questo valore a zero causa l’utilizzo per la stampa dei valori preimpostati in fabbrica per la velocità massima Z."
+msgctxt "speed_z_hop description"
+msgid "The speed at which the vertical Z movement is made for Z Hops. This is typically lower than the print speed since the build plate or machine's gantry is harder to move."
+msgstr "Velocità alla quale viene eseguito il movimento Z verticale per i sollevamenti in Z. In genere è inferiore alla velocità di stampa, dal momento che il piano o il corpo di stampa della macchina sono più difficili da spostare."
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers label"
@@ -2787,7 +3093,7 @@ msgstr "Modalità Combing"
#: fdmprinter.def.json
msgctxt "retraction_combing description"
msgid "Combing keeps the nozzle within already printed areas when traveling. This results in slightly longer travel moves but reduces the need for retractions. If combing is off, the material will retract and the nozzle moves in a straight line to the next point. It is also possible to avoid combing over top/bottom skin areas or to only comb within the infill."
-msgstr ""
+msgstr "La funzione Combing tiene l’ugello all’interno delle aree già stampate durante lo spostamento. In tal modo le corse di spostamento sono leggermente più lunghe ma si riduce l’esigenza di effettuare retrazioni. Se questa funzione viene disabilitata, il materiale viene retratto e l’ugello si sposta in linea retta al punto successivo. È anche possibile evitare il combing sopra le aree del rivestimento esterno superiore/inferiore o effettuare il combing solo nel riempimento."
#: fdmprinter.def.json
msgctxt "retraction_combing option off"
@@ -2859,16 +3165,6 @@ msgctxt "travel_avoid_distance description"
msgid "The distance between the nozzle and already printed parts when avoiding during travel moves."
msgstr "La distanza tra l’ugello e le parti già stampate quando si effettua lo spostamento con aggiramento."
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position label"
-msgid "Start Layers with the Same Part"
-msgstr "Avvio strati con la stessa parte"
-
-#: fdmprinter.def.json
-msgctxt "start_layers_at_same_position description"
-msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
-msgstr "In ciascuno strato inizia la stampa dell’oggetto vicino allo stesso punto, in modo che non si inizia un nuovo strato con la stampa del pezzo con cui è terminato lo strato precedente. Questo consente di ottenere migliori sovrapposizioni e parti piccole, ma aumenta il tempo di stampa."
-
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
@@ -2929,6 +3225,16 @@ msgctxt "retraction_hop_after_extruder_switch description"
msgid "After the machine switched from one extruder to the other, the build plate is lowered to create clearance between the nozzle and the print. This prevents the nozzle from leaving oozed material on the outside of a print."
msgstr "Dopo il passaggio della macchina da un estrusore all’altro, il piano di stampa viene abbassato per creare uno spazio tra l’ugello e la stampa. In tal modo si previene il rilascio di materiale fuoriuscito dall’ugello sull’esterno di una stampa."
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height label"
+msgid "Z Hop After Extruder Switch Height"
+msgstr "Z Hop dopo cambio altezza estrusore"
+
+#: fdmprinter.def.json
+msgctxt "retraction_hop_after_extruder_switch_height description"
+msgid "The height difference when performing a Z Hop after extruder switch."
+msgstr "La differenza di altezza durante l'esecuzione di uno Z Hop dopo il cambio dell'estrusore."
+
#: fdmprinter.def.json
msgctxt "cooling label"
msgid "Cooling"
@@ -3199,6 +3505,11 @@ msgctxt "support_pattern option cross"
msgid "Cross"
msgstr "Incrociata"
+#: fdmprinter.def.json
+msgctxt "support_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Gyroid"
+
#: fdmprinter.def.json
msgctxt "support_wall_count label"
msgid "Support Wall Line Count"
@@ -3260,14 +3571,14 @@ msgid "Distance between the printed initial layer support structure lines. This
msgstr "Indica la distanza tra le linee della struttura di supporto dello strato iniziale stampato. Questa impostazione viene calcolata mediante la densità del supporto."
#: fdmprinter.def.json
-msgctxt "support_infill_angle label"
-msgid "Support Infill Line Direction"
+msgctxt "support_infill_angles label"
+msgid "Support Infill Line Directions"
msgstr "Direzione delle linee di riempimento supporto"
#: fdmprinter.def.json
-msgctxt "support_infill_angle description"
-msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
-msgstr "Indica l’orientamento della configurazione del riempimento per i supporti. La configurazione del riempimento del supporto viene ruotata sul piano orizzontale."
+msgctxt "support_infill_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees."
+msgstr "Elenco di direzioni linee intere da utilizzare. Gli elementi dall'elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell'elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l'intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza l'angolo predefinito di 0 gradi."
#: fdmprinter.def.json
msgctxt "support_brim_enable label"
@@ -3396,8 +3707,8 @@ msgstr "Distanza giunzione supporto"
#: fdmprinter.def.json
msgctxt "support_join_distance description"
-msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
-msgstr "Indica la distanza massima tra le strutture di supporto nelle direzioni X/Y. Quando la distanza tra le strutture è inferiore al valore indicato, le strutture convergono in una unica."
+msgid "The maximum distance between support structures in the X/Y directions. When separate structures are closer together than this value, the structures merge into one."
+msgstr "La distanza massima tra le strutture di supporto nelle direzioni X/Y. Quando la distanza tra le strutture è inferiore al valore indicato, le strutture convergono in una unica."
#: fdmprinter.def.json
msgctxt "support_offset label"
@@ -3442,12 +3753,12 @@ msgstr "Indica l’altezza di riempimento del supporto di una data densità prim
#: fdmprinter.def.json
msgctxt "minimum_support_area label"
msgid "Minimum Support Area"
-msgstr ""
+msgstr "Area minima supporto"
#: fdmprinter.def.json
msgctxt "minimum_support_area description"
msgid "Minimum area size for support polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgstr "Dimensioni minime area per i poligoni del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
#: fdmprinter.def.json
msgctxt "support_interface_enable label"
@@ -3677,62 +3988,95 @@ msgstr "Zig Zag"
#: fdmprinter.def.json
msgctxt "minimum_interface_area label"
msgid "Minimum Support Interface Area"
-msgstr ""
+msgstr "Area minima interfaccia supporto"
#: fdmprinter.def.json
msgctxt "minimum_interface_area description"
-msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Dimensione minima dell'area per i poligoni dell'interfaccia di supporto. I poligoni con un'area più piccola rispetto a questo valore saranno stampati come"
+" supporto normale."
#: fdmprinter.def.json
msgctxt "minimum_roof_area label"
msgid "Minimum Support Roof Area"
-msgstr ""
+msgstr "Area minima parti superiori supporto"
#: fdmprinter.def.json
msgctxt "minimum_roof_area description"
-msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Dimensione minima dell'area per le parti superiori del supporto. I poligoni con un'area più piccola rispetto a questo valore saranno stampati come supporto"
+" normale."
#: fdmprinter.def.json
msgctxt "minimum_bottom_area label"
msgid "Minimum Support Floor Area"
-msgstr ""
+msgstr "Area minima parti inferiori supporto"
#: fdmprinter.def.json
msgctxt "minimum_bottom_area description"
-msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
-msgstr ""
+msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will be printed as normal support."
+msgstr "Dimensione minima dell'area per le parti inferiori del supporto. I poligoni con un'area più piccola rispetto a questo valore saranno stampati come supporto"
+" normale."
#: fdmprinter.def.json
msgctxt "support_interface_offset label"
msgid "Support Interface Horizontal Expansion"
-msgstr ""
+msgstr "Espansione orizzontale interfaccia supporto"
#: fdmprinter.def.json
msgctxt "support_interface_offset description"
msgid "Amount of offset applied to the support interface polygons."
-msgstr ""
+msgstr "Entità di offset applicato ai poligoni di interfaccia del supporto."
#: fdmprinter.def.json
msgctxt "support_roof_offset label"
msgid "Support Roof Horizontal Expansion"
-msgstr ""
+msgstr "Espansione orizzontale parti superiori supporto"
#: fdmprinter.def.json
msgctxt "support_roof_offset description"
msgid "Amount of offset applied to the roofs of the support."
-msgstr ""
+msgstr "Entità di offset applicato alle parti superiori del supporto."
#: fdmprinter.def.json
msgctxt "support_bottom_offset label"
msgid "Support Floor Horizontal Expansion"
-msgstr ""
+msgstr "Espansione orizzontale parti inferiori supporto"
#: fdmprinter.def.json
msgctxt "support_bottom_offset description"
msgid "Amount of offset applied to the floors of the support."
-msgstr ""
+msgstr "Entità di offset applicato alle parti inferiori del supporto."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles label"
+msgid "Support Interface Line Directions"
+msgstr "Direzioni della linea dell'interfaccia di supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Elenco di direzioni linee intere da utilizzare. Gli elementi dall'elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell'elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l'intero elenco è racchiuso tra parentesi quadre. L'elenco predefinito è vuoto, vale a dire che utilizza gli angoli predefiniti (alterna tra 45 e 135 gradi se le interfacce sono abbastanza spesse oppure 90 gradi)."
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles label"
+msgid "Support Roof Line Directions"
+msgstr "Direzioni delle linee di supporto superiori"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Elenco di direzioni linee intere da utilizzare. Gli elementi dall'elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell'elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l'intero elenco è racchiuso tra parentesi quadre. L'elenco predefinito è vuoto, vale a dire che utilizza gli angoli predefiniti (alterna tra 45 e 135 gradi se le interfacce sono abbastanza spesse oppure 90 gradi)."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles label"
+msgid "Support Floor Line Directions"
+msgstr "Direzioni della larghezza della linea di supporto inferiore"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_angles description"
+msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angles (alternates between 45 and 135 degrees if interfaces are quite thick or 90 degrees)."
+msgstr "Elenco di direzioni linee intere da utilizzare. Gli elementi dall'elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell'elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l'intero elenco è racchiuso tra parentesi quadre. L'elenco predefinito è vuoto, vale a dire che utilizza gli angoli predefiniti (alterna tra 45 e 135 gradi se le interfacce sono abbastanza spesse oppure 90 gradi)."
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
@@ -3775,14 +4119,14 @@ msgid "The diameter of a special tower."
msgstr "Corrisponde al diametro di una torre speciale."
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter label"
-msgid "Minimum Diameter"
-msgstr "Diametro minimo"
+msgctxt "support_tower_maximum_supported_diameter label"
+msgid "Maximum Tower-Supported Diameter"
+msgstr "Diametro supportato dalla torre"
#: fdmprinter.def.json
-msgctxt "support_minimal_diameter description"
-msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
-msgstr "È il diametro minimo nelle direzioni X/Y di una piccola area, che deve essere sostenuta da una torre speciale."
+msgctxt "support_tower_maximum_supported_diameter description"
+msgid "Maximum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+msgstr "È il diametro massimo nelle direzioni X/Y di una piccola area, che deve essere sostenuta da una torre speciale."
#: fdmprinter.def.json
msgctxt "support_tower_roof_angle label"
@@ -4278,16 +4622,6 @@ msgctxt "prime_tower_enable description"
msgid "Print a tower next to the print which serves to prime the material after each nozzle switch."
msgstr "Stampa una torre accanto alla stampa che serve per innescare il materiale dopo ogni cambio ugello."
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular label"
-msgid "Circular Prime Tower"
-msgstr "Torre di innesco circolare"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_circular description"
-msgid "Make the prime tower as a circular shape."
-msgstr "Conferisce alla torre di innesco una forma circolare."
-
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
@@ -4328,16 +4662,6 @@ msgctxt "prime_tower_position_y description"
msgid "The y coordinate of the position of the prime tower."
msgstr "Indica la coordinata Y della posizione della torre di innesco."
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow label"
-msgid "Prime Tower Flow"
-msgstr "Flusso torre di innesco"
-
-#: fdmprinter.def.json
-msgctxt "prime_tower_flow description"
-msgid "Flow compensation: the amount of material extruded is multiplied by this value."
-msgstr "Determina la compensazione del flusso: la quantità di materiale estruso viene moltiplicata per questo valore."
-
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
@@ -4348,6 +4672,16 @@ msgctxt "prime_tower_wipe_enabled description"
msgid "After printing the prime tower with one nozzle, wipe the oozed material from the other nozzle off on the prime tower."
msgstr "Dopo la stampa della torre di innesco con un ugello, pulisce il materiale fuoriuscito dall’altro ugello sulla torre di innesco."
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable label"
+msgid "Prime Tower Brim"
+msgstr "Brim torre di innesco"
+
+#: fdmprinter.def.json
+msgctxt "prime_tower_brim_enable description"
+msgid "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type."
+msgstr "Le torri di innesco potrebbero richiedere un'adesione supplementare fornita da un bordo (brim), anche se il modello non lo prevede. Attualmente non può essere utilizzato con il tipo di adesione 'Raft'."
+
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
msgid "Enable Ooze Shield"
@@ -4468,6 +4802,36 @@ msgctxt "remove_empty_first_layers description"
msgid "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle."
msgstr "Rimuovere gli strati vuoti sotto il primo strato stampato, se presenti. La disabilitazione di questa impostazione può provocare la presenza di primi strati vuoti, se l'impostazione di Tolleranza di sezionamento è impostata su Esclusiva o Intermedia."
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Risoluzione massima"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "La dimensione minima di un segmento di linea dopo il sezionamento. Se tale dimensione aumenta, la maglia avrà una risoluzione inferiore. Questo può consentire alla stampante di mantenere la velocità per processare il g-code ed aumenterà la velocità di sezionamento eliminando i dettagli della maglia che non è comunque in grado di processare."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution label"
+msgid "Maximum Travel Resolution"
+msgstr "Risoluzione massima di spostamento"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_travel_resolution description"
+msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
+msgstr "La dimensione minima di un segmento lineare di spostamento dopo il sezionamento. Aumentando tale dimensione, le corse di spostamento avranno meno angoli arrotondati. La stampante può così mantenere la velocità per processare il g-code, ma si può verificare una riduzione della precisione di aggiramento del modello."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation label"
+msgid "Maximum Deviation"
+msgstr "Deviazione massima"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_deviation description"
+msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true."
+msgstr "La deviazione massima consentita quando si riduce la risoluzione per l'impostazione Risoluzione massima. Se si aumenta questo parametro, la stampa sarà meno precisa, ma il g-code sarà più piccolo. Deviazione massima rappresenta il limite per Risoluzione massima; pertanto se le due impostazioni sono in conflitto, verrà considerata vera l'impostazione Deviazione massima."
+
#: fdmprinter.def.json
msgctxt "blackmagic label"
msgid "Special Modes"
@@ -4630,8 +4994,8 @@ msgstr "Levigazione dei profili con movimento spiraliforme"
#: fdmprinter.def.json
msgctxt "smooth_spiralized_contours description"
-msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
-msgstr "Leviga i profili con movimento spiraliforme per ridurre la visibilità della giunzione Z (la giunzione Z dovrebbe essere appena visibile sulla stampa, ma rimane visibile nella vista dello strato). Notare che la levigatura tende a rimuovere le bavature fini della superficie."
+msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+msgstr "Leviga i profili con movimento spiraliforme per ridurre la visibilità della giunzione Z (la giunzione Z dovrebbe essere appena visibile sulla stampa, ma rimane visibile nella visualizzazione a strati). Notare che la levigatura tende a rimuovere le bavature fini della superficie."
#: fdmprinter.def.json
msgctxt "relative_extrusion label"
@@ -4843,26 +5207,6 @@ msgctxt "minimum_polygon_circumference description"
msgid "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details."
msgstr "I poligoni in strati sezionati con una circonferenza inferiore a questo valore verranno scartati. I valori inferiori generano una maglia con risoluzione superiore al costo del tempo di sezionamento. È dedicata in particolare alle stampanti SLA ad alta risoluzione e a modelli 3D molto piccoli, ricchi di dettagli."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Risoluzione massima"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "La dimensione minima di un segmento di linea dopo il sezionamento. Se tale dimensione aumenta, la maglia avrà una risoluzione inferiore. Questo può consentire alla stampante di mantenere la velocità per processare il g-code ed aumenterà la velocità di sezionamento eliminando i dettagli della maglia che non è comunque in grado di processare."
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution label"
-msgid "Maximum Travel Resolution"
-msgstr "Risoluzione massima di spostamento"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_travel_resolution description"
-msgid "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate."
-msgstr "La dimensione minima di un segmento lineare di spostamento dopo il sezionamento. Aumentando tale dimensione, le corse di spostamento avranno meno angoli arrotondati. La stampante può così mantenere la velocità per processare il g-code, ma si può verificare una riduzione della precisione di aggiramento del modello."
-
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5003,16 +5347,6 @@ msgctxt "coasting_speed description"
msgid "The speed by which to move during coasting, relative to the speed of the extrusion path. A value slightly under 100% is advised, since during the coasting move the pressure in the bowden tube drops."
msgstr "È la velocità a cui eseguire lo spostamento durante il Coasting, rispetto alla velocità del percorso di estrusione. Si consiglia di impostare un valore leggermente al di sotto del 100%, poiché durante il Coasting la pressione nel tubo Bowden scende."
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation label"
-msgid "Alternate Skin Rotation"
-msgstr "Rotazione alternata del rivestimento esterno"
-
-#: fdmprinter.def.json
-msgctxt "skin_alternate_rotation description"
-msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
-msgstr "Alterna la direzione di stampa degli strati superiori/inferiori. Normalmente vengono stampati solo diagonalmente. Questa impostazione aggiunge le direzioni solo X e solo Y."
-
#: fdmprinter.def.json
msgctxt "cross_infill_pocket_size label"
msgid "Cross 3D Pocket Size"
@@ -5120,8 +5454,8 @@ msgstr "Abilitazione del supporto conico"
#: fdmprinter.def.json
msgctxt "support_conical_enabled description"
-msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
-msgstr "Funzione sperimentale: realizza aree di supporto più piccole nella parte inferiore che in corrispondenza dello sbalzo."
+msgid "Make support areas smaller at the bottom than at the overhang."
+msgstr "Realizza aree di supporto più piccole nella parte inferiore che in corrispondenza dello sbalzo."
#: fdmprinter.def.json
msgctxt "support_conical_angle label"
@@ -5185,23 +5519,24 @@ msgstr "Indica la distanza media tra i punti casuali introdotti su ciascun segme
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
-msgid "Flow rate compensation max extrusion offset"
+msgid "Flow Rate Compensation Max Extrusion Offset"
msgstr "Offset massimo dell'estrusione di compensazione del flusso"
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
-msgid "The maximum distance in mm to compensate."
-msgstr "La massima distanza in mm da compensare."
+msgid "The maximum distance in mm to move the filament to compensate for changes in flow rate."
+msgstr "Distanza massima in mm di spostamento del filamento per compensare le modifiche nella velocità di flusso."
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor label"
-msgid "Flow rate compensation factor"
+msgid "Flow Rate Compensation Factor"
msgstr "Fattore di compensazione del flusso"
#: fdmprinter.def.json
msgctxt "flow_rate_extrusion_offset_factor description"
-msgid "The multiplication factor for the flow rate -> distance translation."
-msgstr "Il fattore di moltiplicazione per il flusso -> traslazione distanza."
+msgid "How far to move the filament in order to compensate for changes in flow rate, as a percentage of how far the filament would move in one second of extrusion."
+msgstr "Distanza di spostamento del filamento al fine di compensare le modifiche nella velocità di flusso, come percentuale della distanza di spostamento del filamento"
+" in un secondo di estrusione."
#: fdmprinter.def.json
msgctxt "wireframe_enabled label"
@@ -5464,7 +5799,7 @@ msgstr "Indica la distanza tra l'ugello e le linee diagonali verso il basso. Un
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr "Uso di strati adattivi"
#: fdmprinter.def.json
@@ -5474,7 +5809,7 @@ msgstr "Gli strati adattivi calcolano l’altezza degli strati in base alla form
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation label"
-msgid "Adaptive layers maximum variation"
+msgid "Adaptive Layers Maximum Variation"
msgstr "Variazione massima strati adattivi"
#: fdmprinter.def.json
@@ -5484,7 +5819,7 @@ msgstr "La differenza di altezza massima rispetto all’altezza dello strato di
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_variation_step label"
-msgid "Adaptive layers variation step size"
+msgid "Adaptive Layers Variation Step Size"
msgstr "Dimensione variazione strati adattivi"
#: fdmprinter.def.json
@@ -5494,13 +5829,14 @@ msgstr "La differenza in altezza dello strato successivo rispetto al precedente.
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
-msgstr "Soglia strati adattivi"
+msgid "Adaptive Layers Topography Size"
+msgstr "Dimensione della topografia dei layer adattivi"
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold description"
-msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
-msgstr "Soglia per l’utilizzo o meno di uno strato di dimensioni minori. Questo numero è confrontato al valore dell’inclinazione più ripida di uno strato."
+msgid "Target horizontal distance between two adjacent layers. Reducing this setting causes thinner layers to be used to bring the edges of the layers closer together."
+msgstr "Distanza orizzontale target tra due layer adiacenti. Riducendo questa impostazione, i layer più sottili verranno utilizzati per avvicinare i margini dei"
+" layer."
#: fdmprinter.def.json
msgctxt "wall_overhang_angle label"
@@ -5509,8 +5845,9 @@ msgstr "Angolo parete di sbalzo"
#: fdmprinter.def.json
msgctxt "wall_overhang_angle description"
-msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
-msgstr "Le pareti che sbalzano oltre questo angolo verranno stampate utilizzando le impostazioni parete di sbalzo. Quando il valore è 90, nessuna parete sarà trattata come sbalzo."
+msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging. Overhang that gets supported by support will not be treated as overhang either."
+msgstr "Le pareti con uno sbalzo superiore a quest'angolo saranno stampate con le impostazioni per le pareti a sbalzo. Se il valore è 90, nessuna parete sarà trattata"
+" come parete a sbalzo. Nemmeno lo sbalzo supportato dal supporto sarà trattato come tale."
#: fdmprinter.def.json
msgctxt "wall_overhang_speed_factor label"
@@ -5712,6 +6049,198 @@ msgctxt "bridge_fan_speed_3 description"
msgid "Percentage fan speed to use when printing the third bridge skin layer."
msgstr "La velocità della ventola in percentuale da usare per stampare il terzo strato del rivestimento esterno ponte."
+#: fdmprinter.def.json
+msgctxt "clean_between_layers label"
+msgid "Wipe Nozzle Between Layers"
+msgstr "Pulitura ugello tra gli strati"
+
+#: fdmprinter.def.json
+msgctxt "clean_between_layers description"
+msgid "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working."
+msgstr "Se includere il codice G di pulitura ugello tra gli strati. Abilitare questa impostazione potrebbe influire sul comportamento di retrazione al cambio strato. Utilizzare le impostazioni di Retrazione per pulitura per controllare la retrazione in corrispondenza degli strati in cui lo script di pulitura sarà funzionante."
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe label"
+msgid "Material Volume Between Wipes"
+msgstr "Volume di materiale tra le operazioni di pulitura"
+
+#: fdmprinter.def.json
+msgctxt "max_extrusion_before_wipe description"
+msgid "Maximum material, that can be extruded before another nozzle wipe is initiated."
+msgstr "Il massimo volume di materiale, che può essere estruso prima di iniziare la successiva operazione di pulitura ugello."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable label"
+msgid "Wipe Retraction Enable"
+msgstr "Retrazione per pulitura abilitata"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_enable description"
+msgid "Retract the filament when the nozzle is moving over a non-printed area."
+msgstr "Ritrae il filamento quando l'ugello si sta muovendo su un'area non stampata."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount label"
+msgid "Wipe Retraction Distance"
+msgstr "Distanza di retrazione per pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_amount description"
+msgid "Amount to retract the filament so it does not ooze during the wipe sequence."
+msgstr "L'entità di retrazione del filamento in modo che non fuoriesca durante la sequenza di pulitura."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount label"
+msgid "Wipe Retraction Extra Prime Amount"
+msgstr "Entità di innesco supplementare dopo retrazione per pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_extra_prime_amount description"
+msgid "Some material can ooze away during a wipe travel moves, which can be compensated for here."
+msgstr "Qui è possibile compensare l’eventuale trafilamento di materiale che può verificarsi nel corso della pulitura durante il movimento."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed label"
+msgid "Wipe Retraction Speed"
+msgstr "Velocità di retrazione per pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_speed description"
+msgid "The speed at which the filament is retracted and primed during a wipe retraction move."
+msgstr "Indica la velocità alla quale il filamento viene retratto e preparato durante un movimento di retrazione per pulitura."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed label"
+msgid "Wipe Retraction Retract Speed"
+msgstr "Velocità di retrazione per pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_retract_speed description"
+msgid "The speed at which the filament is retracted during a wipe retraction move."
+msgstr "Indica la velocità alla quale il filamento viene retratto durante un movimento di retrazione per pulitura."
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed label"
+msgid "Retraction Prime Speed"
+msgstr "Velocità di innesco dopo la retrazione"
+
+#: fdmprinter.def.json
+msgctxt "wipe_retraction_prime_speed description"
+msgid "The speed at which the filament is primed during a wipe retraction move."
+msgstr "Indica la velocità alla quale il filamento viene preparato durante un movimento di retrazione per pulitura."
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause label"
+msgid "Wipe Pause"
+msgstr "Pausa pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_pause description"
+msgid "Pause after the unretract."
+msgstr "Pausa dopo ripristino."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable label"
+msgid "Wipe Z Hop When Retracted"
+msgstr "Z Hop pulitura durante retrazione"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_enable description"
+msgid "Whenever a retraction is done, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate."
+msgstr "Ogniqualvolta avviene una retrazione, il piano di stampa viene abbassato per creare uno spazio tra l’ugello e la stampa. Questo impedisce l'urto dell'ugello sulla stampa durante gli spostamenti, riducendo la possibilità di far cadere la stampa dal piano."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount label"
+msgid "Wipe Z Hop Height"
+msgstr "Altezza Z Hop pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_amount description"
+msgid "The height difference when performing a Z Hop."
+msgstr "La differenza di altezza durante l’esecuzione di uno Z Hop."
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed label"
+msgid "Wipe Hop Speed"
+msgstr "Velocità di sollevamento (Hop) per pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_hop_speed description"
+msgid "Speed to move the z-axis during the hop."
+msgstr "Velocità di spostamento dell'asse z durante il sollevamento (Hop)."
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x label"
+msgid "Wipe Brush X Position"
+msgstr "Posizione X spazzolino di pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_brush_pos_x description"
+msgid "X location where wipe script will start."
+msgstr "Posizione X in cui verrà avviato lo script di pulitura."
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count label"
+msgid "Wipe Repeat Count"
+msgstr "Conteggio ripetizioni operazioni di pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_repeat_count description"
+msgid "Number of times to move the nozzle across the brush."
+msgstr "Numero di passaggi dell'ugello attraverso lo spazzolino."
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance label"
+msgid "Wipe Move Distance"
+msgstr "Distanza spostamento longitudinale di pulitura"
+
+#: fdmprinter.def.json
+msgctxt "wipe_move_distance description"
+msgid "The distance to move the head back and forth across the brush."
+msgstr "La distanza dello spostamento longitudinale eseguito dalla testina attraverso lo spazzolino."
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size label"
+msgid "Small Hole Max Size"
+msgstr "Dimensione massima foro piccolo"
+
+#: fdmprinter.def.json
+msgctxt "small_hole_max_size description"
+msgid "Holes and part outlines with a diameter smaller than this will be printed using Small Feature Speed."
+msgstr "I fori e i profili delle parti con un diametro inferiore a quello indicato verranno stampati utilizzando Velocità Dettagli di piccole dimensioni."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length label"
+msgid "Small Feature Max Length"
+msgstr "Lunghezza massima dettagli di piccole dimensioni"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_max_length description"
+msgid "Feature outlines that are shorter than this length will be printed using Small Feature Speed."
+msgstr "Profili di dettagli inferiori a questa lunghezza saranno stampati utilizzando Velocità Dettagli di piccole dimensioni."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor label"
+msgid "Small Feature Speed"
+msgstr "Velocità dettagli piccole dimensioni"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor description"
+msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "I dettagli di piccole dimensioni verranno stampati a questa percentuale della velocità di stampa normale. Una stampa più lenta può aiutare in termini di"
+" adesione e precisione."
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 label"
+msgid "Small Feature Initial Layer Speed"
+msgstr "Velocità layer iniziale per dettagli di piccole dimensioni"
+
+#: fdmprinter.def.json
+msgctxt "small_feature_speed_factor_0 description"
+msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy."
+msgstr "I dettagli di piccole dimensioni sul primo layer saranno stampati a questa percentuale della velocità di stampa normale. Una stampa più lenta può aiutare"
+" in termini di adesione e precisione."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5772,6 +6301,218 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
+#~ msgctxt "minimum_interface_area description"
+#~ msgid "Minimum area size for support interface polygons. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Dimensioni minime area per i poligoni di interfaccia del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
+
+#~ msgctxt "minimum_roof_area description"
+#~ msgid "Minimum area size for the roofs of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Dimensioni minime area per le parti superiori del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
+
+#~ msgctxt "minimum_bottom_area description"
+#~ msgid "Minimum area size for the floors of the support. Polygons which have an area smaller than this value will not be generated."
+#~ msgstr "Dimensioni minime area per le parti inferiori del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
+
+#~ msgctxt "skin_alternate_rotation label"
+#~ msgid "Alternate Skin Rotation"
+#~ msgstr "Rotazione alternata del rivestimento esterno"
+
+#~ msgctxt "skin_alternate_rotation description"
+#~ msgid "Alternate the direction in which the top/bottom layers are printed. Normally they are printed diagonally only. This setting adds the X-only and Y-only directions."
+#~ msgstr "Alterna la direzione di stampa degli strati superiori/inferiori. Normalmente vengono stampati solo diagonalmente. Questa impostazione aggiunge le direzioni solo X e solo Y."
+
+#~ msgctxt "flow_rate_max_extrusion_offset label"
+#~ msgid "Flow rate compensation max extrusion offset"
+#~ msgstr "Offset massimo dell'estrusione di compensazione del flusso"
+
+#~ msgctxt "flow_rate_max_extrusion_offset description"
+#~ msgid "The maximum distance in mm to compensate."
+#~ msgstr "La massima distanza in mm da compensare."
+
+#~ msgctxt "flow_rate_extrusion_offset_factor label"
+#~ msgid "Flow rate compensation factor"
+#~ msgstr "Fattore di compensazione del flusso"
+
+#~ msgctxt "flow_rate_extrusion_offset_factor description"
+#~ msgid "The multiplication factor for the flow rate -> distance translation."
+#~ msgstr "Il fattore di moltiplicazione per il flusso -> traslazione distanza."
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive Layers Threshold"
+#~ msgstr "Soglia strati adattivi"
+
+#~ msgctxt "adaptive_layer_height_threshold description"
+#~ msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+#~ msgstr "Soglia per l’utilizzo o meno di uno strato di dimensioni minori. Questo numero è confrontato al valore dell’inclinazione più ripida di uno strato."
+
+#~ msgctxt "wall_overhang_angle description"
+#~ msgid "Walls that overhang more than this angle will be printed using overhanging wall settings. When the value is 90, no walls will be treated as overhanging."
+#~ msgstr "Le pareti che sbalzano oltre questo angolo verranno stampate utilizzando le impostazioni parete di sbalzo. Quando il valore è 90, nessuna parete sarà trattata come sbalzo."
+
+#~ msgctxt "small_feature_speed_factor description"
+#~ msgid "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "I dettagli di piccole dimensioni verranno stampati a questa percentuale della velocità di stampa normale. Una stampa più lenta può aiutare in termini di adesione e precisione."
+
+#~ msgctxt "small_feature_speed_factor_0 label"
+#~ msgid "First Layer Speed"
+#~ msgstr "Velocità primo layer"
+
+#~ msgctxt "small_feature_speed_factor_0 description"
+#~ msgid "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy."
+#~ msgstr "I dettagli di piccole dimensioni sul primo layer saranno stampati a questa percentuale della velocità di stampa normale. Una stampa più lenta può aiutare in termini di adesione e precisione."
+
+#~ msgctxt "ironing_enabled description"
+#~ msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
+#~ msgstr "Ulteriore passaggio sopra la superficie superiore, senza estrusione di materiale. Ha lo scopo di fondere ulteriormente la plastica alla sommità, creando una superficie più uniforme."
+
+#~ msgctxt "start_layers_at_same_position label"
+#~ msgid "Start Layers with the Same Part"
+#~ msgstr "Avvio strati con la stessa parte"
+
+#~ msgctxt "start_layers_at_same_position description"
+#~ msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
+#~ msgstr "In ciascuno strato inizia la stampa dell’oggetto vicino allo stesso punto, in modo che non si inizia un nuovo strato con la stampa del pezzo con cui è terminato lo strato precedente. Questo consente di ottenere migliori sovrapposizioni e parti piccole, ma aumenta il tempo di stampa."
+
+#~ msgctxt "support_infill_angles description"
+#~ msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
+#~ msgstr "Indica l’orientamento della configurazione del riempimento per i supporti. La configurazione del riempimento del supporto viene ruotata sul piano orizzontale."
+
+#~ msgctxt "meshfix_maximum_deviation description"
+#~ msgid "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller."
+#~ msgstr "La deviazione massima consentita quando si riduce la risoluzione per l'impostazione di Risoluzione massima. Se si aumenta questo parametro, la stampa sarà meno precisa, ma il codice g sarà più piccolo."
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code Flavour"
+#~ msgstr "Tipo di codice G"
+
+#~ msgctxt "z_seam_corner description"
+#~ msgid "Control whether corners on the model outline influence the position of the seam. None means that corners have no influence on the seam position. Hide Seam makes the seam more likely to occur on an inside corner. Expose Seam makes the seam more likely to occur on an outside corner. Hide or Expose Seam makes the seam more likely to occur at an inside or outside corner."
+#~ msgstr "Controlla se gli angoli sul profilo del modello influenzano la posizione della giunzione. Nessuno significa che gli angoli non hanno alcuna influenza sulla posizione della giunzione. Nascondi giunzione favorisce la presenza della giunzione su un angolo interno. Esponi giunzione favorisce la presenza della giunzione su un angolo esterno. Nascondi o esponi giunzione favorisce la presenza della giunzione su un angolo interno o esterno."
+
+#~ msgctxt "skin_no_small_gaps_heuristic label"
+#~ msgid "Ignore Small Z Gaps"
+#~ msgstr "Ignora i piccoli interstizi a Z"
+
+#~ msgctxt "skin_no_small_gaps_heuristic description"
+#~ msgid "When the model has small vertical gaps, about 5% extra computation time can be spent on generating top and bottom skin in these narrow spaces. In such case, disable the setting."
+#~ msgstr "Quando il modello presenta piccoli spazi vuoti verticali, circa il 5% del tempo di calcolo supplementare può essere utilizzato per la generazione di rivestimenti esterni superiori ed inferiori in questi interstizi. In questo caso disabilitare l’impostazione."
+
+#~ msgctxt "build_volume_temperature description"
+#~ msgid "The temperature used for build volume. If this is 0, the build volume temperature will not be adjusted."
+#~ msgstr "La temperatura utilizzata per il volume di stampa. Se il valore è 0, la temperatura del volume di stampa non verrà regolata."
+
+#~ msgctxt "limit_support_retractions description"
+#~ msgid "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excesive stringing within the support structure."
+#~ msgstr "Omettere la retrazione negli spostamenti da un supporto ad un altro in linea retta. L'abilitazione di questa impostazione riduce il tempo di stampa, ma può comportare un'eccessiva produzione di filamenti all'interno della struttura del supporto."
+
+#~ msgctxt "max_feedrate_z_override label"
+#~ msgid "Maximum Z Speed"
+#~ msgstr "Velocità massima Z"
+
+#~ msgctxt "max_feedrate_z_override description"
+#~ msgid "The maximum speed with which the build plate is moved. Setting this to zero causes the print to use the firmware defaults for the maximum z speed."
+#~ msgstr "Indica la velocità massima di spostamento del piano di stampa. L’impostazione di questo valore a zero causa l’utilizzo per la stampa dei valori preimpostati in fabbrica per la velocità massima Z."
+
+#~ msgctxt "support_join_distance description"
+#~ msgid "The maximum distance between support structures in the X/Y directions. When seperate structures are closer together than this value, the structures merge into one."
+#~ msgstr "Indica la distanza massima tra le strutture di supporto nelle direzioni X/Y. Quando la distanza tra le strutture è inferiore al valore indicato, le strutture convergono in una unica."
+
+#~ msgctxt "support_minimal_diameter label"
+#~ msgid "Minimum Diameter"
+#~ msgstr "Diametro minimo"
+
+#~ msgctxt "support_minimal_diameter description"
+#~ msgid "Minimum diameter in the X/Y directions of a small area which is to be supported by a specialized support tower."
+#~ msgstr "È il diametro minimo nelle direzioni X/Y di una piccola area, che deve essere sostenuta da una torre speciale."
+
+#~ msgctxt "prime_tower_circular label"
+#~ msgid "Circular Prime Tower"
+#~ msgstr "Torre di innesco circolare"
+
+#~ msgctxt "prime_tower_circular description"
+#~ msgid "Make the prime tower as a circular shape."
+#~ msgstr "Conferisce alla torre di innesco una forma circolare."
+
+#~ msgctxt "prime_tower_flow description"
+#~ msgid "Flow compensation: the amount of material extruded is multiplied by this value."
+#~ msgstr "Determina la compensazione del flusso: la quantità di materiale estruso viene moltiplicata per questo valore."
+
+#~ msgctxt "smooth_spiralized_contours description"
+#~ msgid "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details."
+#~ msgstr "Leviga i profili con movimento spiraliforme per ridurre la visibilità della giunzione Z (la giunzione Z dovrebbe essere appena visibile sulla stampa, ma rimane visibile nella vista dello strato). Notare che la levigatura tende a rimuovere le bavature fini della superficie."
+
+#~ msgctxt "support_conical_enabled description"
+#~ msgid "Experimental feature: Make support areas smaller at the bottom than at the overhang."
+#~ msgstr "Funzione sperimentale: realizza aree di supporto più piccole nella parte inferiore che in corrispondenza dello sbalzo."
+
+#~ msgctxt "extruders_enabled_count label"
+#~ msgid "Number of Extruders that are enabled"
+#~ msgstr "Numero di estrusori abilitati"
+
+#~ msgctxt "machine_nozzle_tip_outer_diameter label"
+#~ msgid "Outer nozzle diameter"
+#~ msgstr "Diametro esterno ugello"
+
+#~ msgctxt "machine_nozzle_head_distance label"
+#~ msgid "Nozzle length"
+#~ msgstr "Lunghezza ugello"
+
+#~ msgctxt "machine_nozzle_expansion_angle label"
+#~ msgid "Nozzle angle"
+#~ msgstr "Angolo ugello"
+
+#~ msgctxt "machine_heat_zone_length label"
+#~ msgid "Heat zone length"
+#~ msgstr "Lunghezza della zona di riscaldamento"
+
+#~ msgctxt "machine_nozzle_heat_up_speed label"
+#~ msgid "Heat up speed"
+#~ msgstr "Velocità di riscaldamento"
+
+#~ msgctxt "machine_nozzle_cool_down_speed label"
+#~ msgid "Cool down speed"
+#~ msgstr "Velocità di raffreddamento"
+
+#~ msgctxt "machine_gcode_flavor label"
+#~ msgid "G-code flavour"
+#~ msgstr "Tipo di codice G"
+
+#~ msgctxt "machine_disallowed_areas label"
+#~ msgid "Disallowed areas"
+#~ msgstr "Aree non consentite"
+
+#~ msgctxt "machine_head_polygon label"
+#~ msgid "Machine head polygon"
+#~ msgstr "Poligono testina macchina"
+
+#~ msgctxt "machine_head_with_fans_polygon label"
+#~ msgid "Machine head & Fan polygon"
+#~ msgstr "Poligono testina macchina e ventola"
+
+#~ msgctxt "gantry_height label"
+#~ msgid "Gantry height"
+#~ msgstr "Altezza gantry"
+
+#~ msgctxt "machine_use_extruder_offset_to_offset_coords label"
+#~ msgid "Offset With Extruder"
+#~ msgstr "Offset con estrusore"
+
+#~ msgctxt "adaptive_layer_height_enabled label"
+#~ msgid "Use adaptive layers"
+#~ msgstr "Uso di strati adattivi"
+
+#~ msgctxt "adaptive_layer_height_variation label"
+#~ msgid "Adaptive layers maximum variation"
+#~ msgstr "Variazione massima strati adattivi"
+
+#~ msgctxt "adaptive_layer_height_variation_step label"
+#~ msgid "Adaptive layers variation step size"
+#~ msgstr "Dimensione variazione strati adattivi"
+
+#~ msgctxt "adaptive_layer_height_threshold label"
+#~ msgid "Adaptive layers threshold"
+#~ msgstr "Soglia strati adattivi"
+
#~ msgctxt "skin_overlap description"
#~ msgid "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall."
#~ msgstr "Entità della sovrapposizione tra il rivestimento e le pareti espressa in percentuale della larghezza della linea del rivestimento esterno. Una leggera sovrapposizione consente alle pareti di essere saldamente collegate al rivestimento. È una percentuale delle larghezze medie delle linee del rivestimento e della parete più interna."
diff --git a/resources/i18n/ja_JP/cura.po b/resources/i18n/ja_JP/cura.po
index e57c3e4cea..def6a45abf 100644
--- a/resources/i18n/ja_JP/cura.po
+++ b/resources/i18n/ja_JP/cura.po
@@ -5,20 +5,20 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 4.0\n"
+"Project-Id-Version: Cura 4.4\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2019-02-26 16:36+0100\n"
-"PO-Revision-Date: 2018-11-06 14:58+0100\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Japanese\n"
+"POT-Creation-Date: 2019-11-05 13:13+0100\n"
+"PO-Revision-Date: 2019-09-23 14:15+0200\n"
+"Last-Translator: Lionbridge \n"
+"Language-Team: Japanese , Japanese \n"
"Language: ja_JP\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.2.1\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:22
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:30
msgctxt "@action"
msgid "Machine Settings"
msgstr "プリンターの設定"
@@ -40,13 +40,13 @@ msgctxt "@item:inlistbox"
msgid "G-code File"
msgstr "G-codeファイル"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:67
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:66
msgctxt "@error:not supported"
msgid "GCodeWriter does not support non-text mode."
msgstr "GCodeWriter は非テキストモードはサポートしていません。"
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
-#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:72
+#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:88
msgctxt "@warning:status"
msgid "Please prepare G-code before exporting."
msgstr "エクスポートする前にG-codeの準備をしてください。"
@@ -56,7 +56,7 @@ msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "3Dモデルアシスタント"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:86
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:92
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,72 +70,50 @@ msgstr ""
"